home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1997 #3 / Amiga Plus CD - 1997 - No. 03.iso / pd / programmierung / alienbreed3d2_src / cheesesauce / proplayer.a < prev    next >
Text File  |  1997-01-31  |  119KB  |  3,508 lines

  1. ;============================================================================
  2. ;   proplayer.a
  3. ;   ~~~~~~~~~~~
  4. ; $VER: proplayer 6.0 (08.03.1995)
  5. ;
  6. ; The music player routine for MMD0/MMD1/MMD2 MED/OctaMED
  7. ; four-channel modules.
  8. ;
  9. ; Copyright © 1995 Teijo Kinnunen and RBF Software.
  10. ;
  11. ; Written by Teijo Kinnunen.
  12. ; Comments/questions/bug reports can be sent to:
  13. ;   Teijo Kinnunen
  14. ;   Oksantie 19
  15. ;   FIN-86300  OULAINEN
  16. ;   FINLAND
  17. ;   email: kinnunen@stekt.oulu.fi
  18. ;
  19. ; See OctaMED docs for conditions about using these routines.
  20. ; Comments/questions about distribution and usage conditions
  21. ; should be directed to RBF Software. (Email: rbfsoft@cix.compulink.co.uk)
  22. ;
  23. ;============================================================================
  24.  
  25. ;****** Feature control ******
  26. ;
  27. MIDI        EQU 0   ;1 = include MIDI code
  28. AUDDEV      EQU 0   ;1 = allocate channels using audio.device
  29. SYNTH       EQU 1   ;1 = include synth-sound handler
  30. CHECK       EQU 1   ;1 = do range checkings (track, sample in mem etc.)
  31. RELVOL      EQU 1   ;1 = include relative volume handling code
  32. IFFMOCT     EQU 1   ;1 = play IFF multi-octave samples/ExtSamples correctly
  33. HOLD        EQU 1   ;1 = handle hold/decay
  34. PLAYMMD0    EQU 1   ;1 = play old MMD0 modules
  35. AURA        EQU 0   ;1 = support the Aura sampler
  36. ;
  37. ; The less features you include, the faster and shorter the play-routine
  38. ; will be.
  39. ;
  40. ; NOTE: Using the Aura will cause Enforcer hits (LONG-READ/WRITE at addr $70).
  41. ; This is normal, and can't be avoided.
  42.  
  43. ;****** Timing control ******
  44. ;
  45. VBLANK  EQU 0   ;1 = use VBlank interrupt (when absolutely necessary)
  46. CIAB    EQU 1   ;1 = use CIA timers (default)
  47. ;
  48. ; Please use CIAB whenever possible to avoid problems with variable
  49. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  50. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  51. ; then you just call _IntHandler for each timing pulse.
  52.  
  53. ;============================================================================
  54.  
  55. ;If you are making a demo/game with only a single tune you'd like to
  56. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  57. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  58. ;You have to insert the module name to the INCBIN statement (located near the
  59. ;end of this file, on line 2052).
  60.  
  61. EASY    EQU 0
  62.  
  63. ;Call _startmusic to play the music, and _endmusic to stop it (before
  64. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  65. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  66. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  67.  
  68. ;============================================================================
  69.  
  70. ; The MMD structure offsets
  71. mmd_id      EQU 0
  72. mmd_modlen  EQU 4
  73. ;mmd_songinfo    EQU 8
  74. ; these two for MMD2s only!
  75. mmd_psecnum EQU 12
  76. mmd_pseq    EQU 14
  77. ;
  78. ;mmd_blockarr    EQU 16
  79. mmd_smplarr EQU 24
  80. ;mmd_expdata EQU 32
  81. mmd_pstate  EQU 40 ; <0 = play song, 0 = don't play, >0 = play block
  82. mmd_pblock  EQU 42
  83. mmd_pline   EQU 44
  84. mmd_pseqnum EQU 46
  85. mmd_counter EQU 50
  86. ;mmd_songsleft   EQU 51
  87.  
  88. ; The Song structure
  89. ; Instrument data here (504 bytes = 63 * 8)
  90. ;msng_numblocks  EQU 504
  91. msng_songlen    EQU 506
  92. msng_playseq    EQU 508
  93. msng_deftempo   EQU 764
  94. msng_playtransp EQU 766
  95. msng_flags  EQU 767
  96. msng_flags2 EQU 768
  97. msng_tempo2 EQU 769
  98. ; msng_trkvol applies to MMD0/MMD1 only.
  99. msng_trkvol EQU 770
  100. msng_mastervol  EQU 786
  101. ;msng_numsamples EQU 787
  102. ; Fields below apply to MMD2 modules only.
  103. ;msng_pseqs  EQU 508
  104. msng_sections   EQU 512
  105. msng_trkvoltbl  EQU 516
  106. msng_numtracks  EQU 520
  107. msng_numpseqs   EQU 522
  108.  
  109. ; Instrument data
  110. inst_repeat EQU 0
  111. inst_replen EQU 2
  112. inst_midich EQU 4
  113. inst_midipreset EQU 5
  114. inst_svol   EQU 6
  115. inst_strans EQU 7
  116.  
  117. ; Audio hardware offsets
  118. ac_ptr  EQU $00
  119. ac_len  EQU $04
  120. ac_per  EQU $06
  121. ac_vol  EQU $08
  122.  
  123. ; Trackdata sizes
  124. T03SZ       EQU 106
  125. T415SZ      EQU 22
  126. ;offset of trk_audioaddr
  127. TAAOFFS     EQU 24
  128. TTMPVOLOFFS EQU 102
  129.  
  130. ; Maximum number of tracks allowed. If you don't need this much tracks,
  131. ; you can decrease the number to save some space. (Be sure that the
  132. ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
  133. ; value = 4.)
  134. MAX_NUMTRACKS   EQU 64
  135.  
  136. ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
  137. ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
  138. MAX_MMD1_TRACKS EQU 16
  139.  
  140. ; Aura output handling routines
  141.     IFNE    AURA
  142.         ;also includes the SECTION cmd...
  143.         INCLUDE "aura.a"
  144.     ENDC
  145.     IFEQ    AURA
  146.         SECTION "text",CODE
  147.     ENDC
  148.  
  149.     IFNE    EASY
  150.  
  151.         XDEF    _startmusic,_endmusic
  152.  
  153. _startmusic lea easymod,a2
  154.         bsr.s   _RelocModule
  155.         bsr.w   _InitPlayer
  156.         lea easymod,a0
  157.         bra.w   _PlayModule
  158.  
  159. _endmusic   bra.w   _RemPlayer
  160. ; ***** The relocation routine *****
  161. reloci      move.l  24(a2),d0
  162.         beq.s   xloci
  163.         movea.l d0,a0
  164.         moveq   #0,d0
  165.         move.b  msng_numsamples(a1),d0
  166.         subq.b  #1,d0
  167. relocs      bsr.s   relocentr
  168.         move.l  -4(a0),d3
  169.         beq.s   nosyn
  170.         move.l  d3,a3
  171.         tst.w   4(a3)
  172.         bpl.s   nosyn
  173.         move.w  20(a3),d2
  174.         lea 278(a3),a3
  175.         subq.w  #1,d2
  176. relsyn      add.l   d3,(a3)+
  177.         dbf d2,relsyn
  178. nosyn       dbf     d0,relocs
  179. xloci       rts
  180. norel       addq.l  #4,a0
  181.         rts
  182. relocentr   tst.l   (a0)
  183.         beq.s   norel
  184.         add.l   d1,(a0)+
  185.         rts
  186. _RelocModule    movem.l a2-a4/d2-d4,-(sp)
  187.         move.l  a2,d1
  188.         bsr.s   relocp
  189.         movea.l mmd_songinfo(a2),a1
  190.         bsr.s   reloci
  191.         move.b  mmd_songsleft(a2),d4
  192. rel_lp      bsr.s   relocb
  193.         cmp.b   #'2',3(a2)
  194.         bne.s   norelmmd2
  195.         bsr.w   relocmmd2sng
  196. norelmmd2   move.l  mmd_expdata(a2),d0
  197.         beq.s   rel_ex
  198.         move.l  d0,a0
  199.         bsr.s   relocentr
  200.         bsr.s   relocentr
  201.         addq.l  #4,a0
  202.         bsr.s   relocentr
  203.         addq.l  #4,a0
  204.         bsr.s   relocentr
  205.         addq.l  #8,a0
  206.         bsr.s   relocentr
  207.         addq.l  #4,a0
  208.         bsr.s   relocentr
  209.         bsr.s   relocentr
  210.         addq.l  #4,a0
  211.         bsr.s   relocentr
  212.         bsr.s   relocmdd
  213.         subq.b  #1,d4
  214.         bcs.s   rel_ex
  215.         move.l  d0,a0
  216.         move.l  (a0),d0
  217.         beq.s   rel_ex
  218.         move.l  d0,a2
  219.         bsr.s   relocp
  220.         movea.l 8(a2),a1
  221.         bra.s   rel_lp
  222. rel_ex      movem.l (sp)+,d2-d4/a2-a4
  223.         rts
  224. relocp      lea mmd_songinfo(a2),a0
  225.         bsr.s   relocentr
  226.         addq.l  #4,a0
  227.         bsr.s   relocentr
  228.         addq.l  #4,a0
  229.         bsr.s   relocentr
  230.         addq.l  #4,a0
  231.         bra.s   relocentr
  232. relocb      move.l  mmd_blockarr(a2),d0
  233.         beq.s   xlocb
  234.         movea.l d0,a0
  235.         move.w  msng_numblocks(a1),d0
  236.         subq.b  #1,d0
  237. rebl        bsr relocentr
  238.         dbf     d0,rebl
  239.         cmp.b   #'T',3(a2)
  240.         beq.s   xlocb
  241.         cmp.b   #'1',3(a2)
  242.         bge.s   relocbi
  243. xlocb       rts
  244. relocmdd    move.l  d0,-(sp)
  245.         tst.l   -(a0)
  246.         beq.s   xlocmdd
  247.         movea.l (a0),a0
  248.         move.w  (a0),d0
  249.         addq.l  #8,a0
  250. mddloop     beq.s   xlocmdd
  251.         bsr relocentr
  252.         bsr.s   relocdmp
  253.         subq.w  #1,d0
  254.         bra.s   mddloop
  255. xlocmdd     move.l  (sp)+,d0
  256.         rts
  257. relocdmp    move.l  -4(a0),d3
  258.         beq.s   xlocdmp
  259.         exg.l   a0,d3
  260.         addq.l  #4,a0
  261.         bsr relocentr
  262.         move.l  d3,a0
  263. xlocdmp     rts
  264. relocbi     move.w  msng_numblocks(a1),d0
  265.         move.l  a0,a3
  266. biloop      subq.w  #1,d0
  267.         bmi.s   xlocdmp
  268.         move.l  -(a3),a0
  269.         addq.l  #4,a0
  270.         bsr relocentr
  271.         tst.l   -(a0)
  272.         beq.s   biloop
  273.         move.l  (a0),a0
  274.         bsr relocentr
  275.         bsr relocentr
  276.         addq.l  #4,a0
  277.         bsr relocentr
  278.         tst.l   -(a0)
  279.         bne.s   relocpgtbl
  280.         bra.s   biloop
  281. relocmmd2sng    move.l  mmd_songinfo(a2),a0
  282.         lea msng_pseqs(a0),a0
  283.         bsr relocentr
  284.         bsr relocentr
  285.         bsr relocentr
  286.         move.w  2(a0),d0
  287.         move.l  -12(a0),a0
  288.         subq.w  #1,d0
  289. psqtblloop  bsr relocentr
  290.         dbf d0,psqtblloop
  291.         rts
  292. relocpgtbl  movea.l (a0),a4
  293.         move.w  (a4),d2
  294.         subq.w  #1,d2
  295.         lea 4(a4),a0
  296. pgtblloop   bsr relocentr
  297.         dbf d2,pgtblloop
  298.         bra biloop
  299.     ENDC
  300.  
  301. ; -------- _ChannelOff: Turn off a channel -------------------------------
  302. _ChannelOff:    ;d0 = channel #
  303.         lea DB,a0
  304.         lea trackdataptrs-DB(a0),a1
  305.         lsl.w   #2,d0
  306.         adda.w  d0,a1
  307.         lsr.w   #2,d0
  308.         movea.l (a1),a1
  309.         move.b  trk_outputdev(a1),d1
  310.     IFNE    AURA
  311.         beq.s   choff_outstd
  312.         subq.b  #1,d1
  313.         bne.s   notamigatrk ;unknown type... do nothing
  314.         jmp _StopAura(pc)   ;AURA off
  315. choff_outstd
  316.     ENDC
  317.     IFEQ    AURA
  318.         bne.s   notamigatrk
  319.     ENDC
  320.     IFNE    MIDI
  321.         move.b  trk_prevmidin(a1),d1    ;first: is it MIDI??
  322.         beq.s   notcomidi   ;not a midi note
  323. ; -------- TURN OFF MIDI TRACK -------------------------------------------
  324.         lea noteondata-DB(a0),a0
  325. choff_midi: clr.b   trk_prevmidin(a1)
  326.         move.b  d1,1(a0)
  327.         bmi.s   notamigatrk
  328.         move.b  trk_prevmidich(a1),(a0) ;prev midi channel
  329.         clr.b   2(a0)
  330.         or.b    #$90,(a0)       ;note off
  331.         moveq   #3,d0
  332.         bra.w   _AddMIDIData
  333.     ENDC
  334. notcomidi:  cmp.b   #4,d0
  335.         bge.s   notamigatrk
  336. ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
  337.     IFNE    SYNTH
  338.         clr.l   trk_synthptr(a1)
  339.         clr.b   trk_synthtype(a1)
  340.     ENDC
  341.         clr.w   trk_soffset(a1)
  342.         moveq   #1,d1
  343.         lsl.w   d0,d1
  344.         move.w  d1,$dff096
  345. notamigatrk:    rts
  346.  
  347. ; -------- SoundOff: Turn off all channels -------------------------------
  348. SoundOff:   move.l  d2,-(sp)
  349.         moveq   #MAX_NUMTRACKS-1,d2
  350. SO_loop0    move.l  d2,d0
  351.         bsr.s   _ChannelOff
  352.         dbf d2,SO_loop0
  353.         clr.l   _module     ;play nothing
  354.         move.l  (sp)+,d2
  355. SO_rts      rts
  356.  
  357. ; -------- _PlayNote: The note playing routine ---------------------------
  358. _PlayNote:  ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  359. ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
  360.         move.l  a3,d4
  361.         beq.s   SO_rts
  362.         moveq   #0,d4
  363.         bset    d7,d4   ;d4 is mask for this channel
  364.         movea.l mmd_smplarr(a2),a0
  365.         add.w   d3,d3           ;d3 = instr.num << 2
  366.         add.w   d3,d3
  367.         move.l  0(a0,d3.w),d5       ;get address of instrument
  368.     IFNE    MIDI
  369.         bne.s   inmem
  370.         tst.b   inst_midich(a3)     ;is MIDI channel set?
  371.     ENDC
  372.     IFNE    CHECK
  373.         beq.w   pnote_rts       ; NO!!!
  374.     ENDC
  375. ; -------- ADD TRANSPOSE -------------------------------------------------
  376. inmem       add.b   msng_playtransp(a4),d1  ;add play transpose
  377.         add.b   inst_strans(a3),d1  ;and instr. transpose
  378.     IFNE    AURA
  379.         cmp.w   #3,d7
  380.         bne.s   pn_norelch3
  381.         tst.b   playing_aura-DB(a6)
  382.         bne.s   pn_offaura
  383. pn_norelch3
  384.     ENDC
  385.         move.b  trk_outputdev(a5),d3
  386.         beq.s   pn_offami
  387.     IFNE    AURA
  388.         subq.b  #1,d3
  389.         bne.s   noprevmidi
  390. pn_offaura  jsr _StopAura(pc)
  391.     ENDC
  392.         bra.s   noprevmidi      ;dunno.. unsupported type
  393.     
  394. ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
  395. pn_offami   cmp.b   #4,d7
  396.         bge.s   nodmaoff    ;track # >= 4: not an Amiga channel
  397.         move.l  d5,a1
  398.     IFNE    SYNTH
  399.         tst.l   d5
  400.         beq.s   stpdma
  401.         tst.b   trk_synthtype(a5)
  402.         ble.s   stpdma      ;prev. type = sample/hybrid
  403.         cmp.w   #-1,4(a1)   ;type == SYNTHETIC??
  404.         beq.s   nostpdma
  405.     ENDC
  406. stpdma:     move.w  d4,$dff096      ;stop this channel (dmacon)
  407. nostpdma:
  408.     IFNE    SYNTH
  409.         clr.l   trk_synthptr(a5)
  410.     ENDC
  411. nodmaoff:   subq.b  #1,d1
  412.     IFNE    MIDI
  413. ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
  414.         move.b  trk_prevmidin(a5),d3    ;get prev. midi note
  415.         beq.s   noprevmidi
  416.         clr.b   trk_prevmidin(a5)
  417.         lea noteondata+2-DB(a6),a0
  418.         clr.b   (a0)
  419.         move.b  d3,-(a0)
  420.         bmi.s   noprevmidi
  421.         move.b  trk_prevmidich(a5),-(a0) ;prev midi channel
  422.         or.b    #$90,(a0)        ;note off
  423.         move.w  d1,-(sp)
  424.         moveq   #3,d0
  425.         bsr.w   _AddMIDId
  426.         move.w  (sp)+,d1
  427. noprevmidi
  428. ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
  429.         tst.b   inst_midich(a3)
  430.         bne.w   handleMIDInote
  431.     ENDC
  432. ; -------- TEST OUTPUT DEVICE AND BRANCH IF NOT STD ----------------------
  433.     IFEQ    MIDI
  434. noprevmidi
  435.     ENDC
  436.         tst.b   trk_outputdev(a5)
  437.         bne.w   handlenonstdout
  438. ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
  439.     IFNE    CHECK
  440.         cmp.w   #4,d7       ;track > 3???
  441.         bge.w   pnote_rts   ;no Amiga instruments here!!!
  442.     ENDC
  443. ; handle decay (for tracks 0 - 3 only!!)
  444.     IFNE    HOLD
  445.         clr.b   trk_fadespd(a5)     ;no fade yet..
  446.         move.b  trk_initdecay(a5),trk_decay(a5) ;set decay
  447.     ENDC
  448.         clr.w   trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  449.         or.w    d4,dmaonmsk-DB(a6)
  450.         move.l  d5,a0
  451.     IFNE    SYNTH
  452. ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
  453.         tst.w   4(a0)
  454.         bmi.w   handleSynthnote
  455.         clr.b   trk_synthtype(a5)
  456.     ENDC
  457. ; -------- CHECK NOTE RANGE ----------------------------------------------
  458. tlwtst0     tst.b   d1
  459.         bpl.s   notenot2low
  460.         add.b   #12,d1  ;note was too low, octave up
  461.         bra.s   tlwtst0
  462. notenot2low cmp.b   #62,d1
  463.         ble.s   endpttest
  464.         sub.b   #12,d1  ;note was too high, octave down
  465. endpttest
  466.         moveq   #0,d2
  467.         moveq   #0,d3
  468.         moveq   #6,d4   ;skip (stereo+hdr) offset
  469.         lea _periodtable+32-DB(a6),a1
  470.         move.b  trk_finetune(a5),d2 ;finetune value
  471.         add.b   d2,d2
  472.         add.b   d2,d2       ;multiply by 4...
  473.         ext.w   d2      ;extend
  474.         movea.l 0(a1,d2.w),a1   ;period table address
  475.         move.w  4(a0),d0    ;(Instr hdr in a0)
  476.         btst    #5,d0
  477.         beq.s   gid_nostereo
  478.         move.b  d7,d5
  479.         and.b   #3,d5
  480.         beq.s   gid_nostereo    ;ch 0/4 = play left (norm.)
  481.         cmp.b   #3,d5
  482.         beq.s   gid_nostereo    ;also for ch 3/7
  483.         add.l   (a0),d4     ;play right channel
  484. gid_nostereo
  485.     IFNE    IFFMOCT
  486.         and.w   #$F,d0
  487.         bne.s   gid_notnormal   ;note # in d1 (0 - ...)
  488.     ENDC
  489. gid_cont_ext    move.l  a1,trk_periodtbl(a5)
  490.         add.b   d1,d1
  491.         move.w  0(a1,d1.w),d5 ;put period to d5
  492.         move.l  a0,d0
  493.         move.l  (a0),d1     ;length
  494.         add.l   d4,d0       ;skip hdr and stereo
  495.         add.l   d0,d1       ;sample end pointer
  496.         move.w  inst_repeat(a3),d2
  497.         move.w  inst_replen(a3),d3
  498.     IFNE    IFFMOCT
  499.         bra gid_setrept
  500. gid_addtable    dc.b    0,6,12,18,24,30
  501. gid_divtable    dc.b    31,7,3,15,63,127
  502. gid_notnormal   cmp.w   #7,d0
  503.         blt.s   gid_not_ext
  504.         suba.w  #48,a1
  505.         bra.s   gid_cont_ext
  506. gid_not_ext move.l  d7,-(sp)
  507.         moveq   #0,d7
  508.         move.w  d1,d7
  509.         divu    #12,d7  ;octave #
  510.         move.l  d7,d5
  511.         cmp.w   #6,d7   ;if oct > 5, oct = 5
  512.         blt.s   nohioct
  513.         moveq   #5,d7
  514. nohioct     swap    d5  ;note number in this oct (0-11) is in d5
  515.         move.l  (a0),d1
  516.         cmp.w   #6,d0
  517.         ble.s   nounrecit
  518.         moveq   #6,d0
  519. nounrecit   add.b   gid_addtable-1(pc,d0.w),d7
  520.         move.b  gid_divtable-1(pc,d0.w),d0
  521.         divu    d0,d1   ;get length of the highest octave
  522.         swap    d1
  523.         clr.w   d1
  524.         swap    d1
  525.         move.l  d1,d0       ;d0 and d1 = length of the 1st oct
  526.         move.w  inst_repeat(a3),d2
  527.         move.w  inst_replen(a3),d3
  528.         moveq   #0,d6
  529.         move.b  shiftcnt(pc,d7.w),d6
  530.         lsl.w   d6,d2
  531.         lsl.w   d6,d3
  532.         lsl.w   d6,d1
  533.         move.b  mullencnt(pc,d7.w),d6
  534.         mulu    d6,d0       ;offset of this oct from 1st oct
  535.         add.l   a0,d0       ;add base address to offset
  536.         add.l   d4,d0       ;skip header + stereo
  537.         add.l   d0,d1
  538.         move.l  a1,trk_periodtbl(a5)
  539.         add.b   octstart(pc,d7.w),d5
  540.         add.b   d5,d5
  541.         move.w  0(a1,d5.w),d5
  542.         move.l  (sp)+,d7
  543.         bra.s   gid_setrept
  544. shiftcnt:   dc.b    4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
  545.         dc.b    3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
  546. mullencnt:  dc.b    15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
  547.         dc.b    7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
  548. octstart:   dc.b    12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
  549.         dc.b    0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
  550.     ENDC
  551. gid_setrept add.l   d2,d2
  552.         add.l   d0,d2       ;rep. start pointer
  553.         cmp.w   #1,d3
  554.         bhi.s   gid_noreplen2
  555.         moveq   #0,d3       ;no repeat
  556.         bra.s   gid_cont
  557. gid_noreplen2   add.l   d3,d3
  558.         add.l   d2,d3       ;rep. end pointer
  559.  
  560. ; -------- CALCULATE START/END ADDRESSES ---------------------------------
  561. gid_cont    moveq   #0,d4
  562.         move.w  trk_soffset(a5),d4
  563.         add.l   d4,d0
  564.         cmp.l   d0,d1
  565.         bhi.s   pn_nooffsovf
  566.         sub.l   d4,d0
  567. pn_nooffsovf    movea.l trk_audioaddr(a5),a1 ;base of this channel's regs
  568.         move.l  d0,(a1)+        ;push ac_ptr
  569.         moveq   #0,d4
  570.         move.b  trk_previnstr(a5),d4
  571.         lea flags-DB(a6),a0
  572.         btst    #0,0(a0,d4.w)       ;test flags.SSFLG_LOOP
  573.         bne.s   repeat
  574.         
  575.         move.l  #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  576.         move.w  #1,trk_samplelen(a5)    ;length: 1 word
  577.         sub.l   d0,d1
  578.         lsr.l   #1,d1           ;shift length right
  579.         move.w  d1,(a1)+        ;and push to ac_len
  580.         bra.s   retsn1
  581.  
  582. repeat      move.l  d2,trk_sampleptr(a5)
  583.         move.l  d3,d1
  584.         sub.l   d0,d1
  585.         lsr.l   #1,d1
  586.         move.w  d1,(a1)+    ;ac_len
  587.         sub.l   d2,d3
  588.         lsr.l   #1,d3
  589.         move.w  d3,trk_samplelen(a5)
  590.                 
  591. retsn1      move.w  d5,trk_prevper(a5)
  592.     IFNE    SYNTH
  593.         tst.b   trk_synthtype(a5)
  594.         bne.w   hSn2
  595.     ENDC
  596. pnote_rts   rts
  597.  
  598. handlenonstdout
  599.     IFNE    AURA
  600.         move.b  trk_outputdev(a5),d0
  601.         subq.b  #1,d0
  602.         bne.s   hnso_notaura
  603. ; -------- AURA NOTE PLAYER ROUTINE --------------------------------------
  604. ;   a0 = sample pointer, already set
  605.         moveq   #0,d0
  606.         move.w  trk_soffset(a5),d0
  607.         lea _periodtable+32-DB(a6),a1
  608.         move.b  trk_finetune(a5),d2 ;finetune value
  609.         add.b   d2,d2
  610.         add.b   d2,d2
  611.         ext.w   d2
  612.         movea.l 0(a1,d2.w),a1       ;period table address
  613.         add.b   d1,d1
  614.         move.w  0(a1,d1.w),d1
  615.         moveq   #0,d2           ;end offset = 0
  616.         jsr _PlayAura(pc)
  617. hnso_notaura
  618.     ENDC
  619.         rts
  620.  
  621.     IFNE    MIDI
  622. ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
  623. handleMIDInote:
  624.     IFNE    PLAYMMD0
  625.         cmp.b   #'1',3(a2)
  626.         bge.s   plr_mmd1_3
  627.         add.b   #24,d1
  628. plr_mmd1_3
  629.     ENDC
  630. ; -------- CHECK & SCALE VOLUME ------------------------------------------
  631.         move.b  trk_prevvol(a5),d2 ;temporarily save the volume
  632.     IFNE    RELVOL
  633. ; -------- GetRelVol: Calculate track volume -----------------------------
  634.         ext.w   d2
  635.         mulu    trk_trackvol(a5),d2
  636.         lsr.w   #7,d2
  637.     ENDC
  638.     IFEQ    RELVOL
  639.         lsl.b   #1,d2
  640.     ENDC
  641.         subq.b  #1,d2       ;if 128 => 127
  642.         bpl.s   hmn_notvolu0
  643.         moveq   #0,d2
  644. hmn_notvolu0
  645.         moveq   #0,d5
  646. ; -------- CHECK MIDI CHANNEL --------------------------------------------
  647.         move.b  inst_midich(a3),d5 ;get midi chan of this instrument
  648.         bpl.s   hmn_nosmof  ;bit 7 clear
  649.         clr.b   trk_prevmidin(a5)   ;suppress note off!
  650.         bra.s   hmn_smof
  651. hmn_nosmof  move.b  d1,trk_prevmidin(a5)
  652. hmn_smof    and.b   #$1F,d5     ;clear all flag bits etc...
  653.         subq.b  #1,d5       ;from 1-16 to 0-15
  654.         move.b  d5,trk_prevmidich(a5)   ;save to prev midi channel
  655.  
  656. ; -------- CHECK MIDI PRESET ---------------------------------------------
  657.         moveq   #0,d0
  658.         move.b  trk_previnstr(a5),d0
  659.         add.w   d0,d0
  660.         lea ext_midipsets-DB(a6),a1
  661.         move.w  0(a1,d0.w),d0   ;get preset #
  662.         beq.s   nochgpres   ;zero = no preset
  663.         lea prevmidicpres-DB(a6),a1
  664.         adda.w  d5,a1
  665.         adda.w  d5,a1
  666.         cmp.w   (a1),d0     ;is this previous preset ??
  667.         beq.s   nochgpres   ;yes...no need to change
  668.         move.w  d0,(a1)     ;save preset to prevmidicpres
  669.         subq.w  #1,d0       ;sub 1 to get 0 - 127
  670.         btst    #6,inst_midich(a3)
  671.         bne.s   hmn_extpreset
  672. ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
  673. hmn_ordpreset   lea preschgdata+1-DB(a6),a0
  674.         move.b  d0,(a0)     ;push the number to second byte
  675.         moveq   #2,d0
  676. hmn_sendpreset  move.b  #$c0,-(a0)  ;command: $C
  677.         or.b    d5,(a0)     ;"or" midi channel
  678.         move.w  d1,-(sp)
  679.         bsr.w   _AddMIDId
  680.         move.w  (sp)+,d1
  681.         tst.b   d2
  682.         beq.s   hmn_suppress    ;vol = 0, don't send NOTE ON
  683.  
  684. ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
  685. nochgpres   lea bytesinnotebuff-DB(a6),a0
  686.         movea.l a0,a1
  687.         adda.w  (a0)+,a0
  688.         or.b    #$90,d5     ;MIDI: Note on
  689.         move.b  d5,(a0)+    ;MIDI msg Note on & channel
  690.         move.b  d1,(a0)+    ;MIDI msg note #
  691.         move.b  d2,(a0)     ;MIDI msg volume
  692.         beq.s   hmn_suppress    ;vol = 0 -> no note
  693.         addq.w  #3,(a1)
  694.         rts
  695. hmn_suppress    st  trk_prevmidin(a5)
  696.         rts
  697.  
  698. ; -------- HANDLE EXTENDED PRESET ----------------------------------------
  699. hmn_extpreset   cmp.w   #100,d0
  700.         blt.s   hmn_ordpreset
  701.         moveq   #99,d3
  702. hmn_loop100 sub.w   #100,d0
  703.         addq.b  #1,d3
  704.         cmp.w   #100,d0
  705.         bge.s   hmn_loop100
  706.         lea preschgdata+2-DB(a6),a0
  707.         move.b  d0,(a0)     ;push the <= 99 number
  708.         move.b  d3,-(a0)    ;push the >= 100 number
  709.         moveq   #3,d0
  710.         bra.s   hmn_sendpreset
  711.     ENDC
  712.  
  713.     IFNE    SYNTH
  714. ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
  715. handleSynthnote move.b  d1,trk_prevnote2(a5)
  716.         move.l  a0,trk_synthptr(a5)
  717.         cmp.w   #-2,4(a0)   ;HYBRID??
  718.         bne.s   hSn_nossn
  719.         st  trk_synthtype(a5)
  720.         movea.l 278(a0),a0  ;yep, get the waveform pointer
  721.         bra.w   tlwtst0     ;go and play it
  722. hSn_nossn:  move.b  #1,trk_synthtype(a5)
  723.         lea _periodtable+32-DB(a6),a1
  724.         move.b  trk_finetune(a5),d0 ;finetune value
  725.         add.b   d0,d0
  726.         add.b   d0,d0       ;multiple by 4...
  727.         ext.w   d0      ;extend
  728.         movea.l 0(a1,d0.w),a1   ;period table address
  729.         suba.w  #48,a1
  730.         move.l  a1,trk_periodtbl(a5) ;save table ptr for synth periods
  731.         add.w   d1,d1
  732.         move.w  0(a1,d1.w),d1
  733.         move.w  d1,trk_prevper(a5)
  734.         clr.l   trk_sampleptr(a5)
  735. hSn2:       lea trk_arpgoffs(a5),a1
  736.         clr.l   (a1)+
  737.         clr.l   (a1)+
  738.         btst    #0,trk_miscflags(a5)
  739.         bne.s   hSn_cmdE ;cmd E given, don't clear trk_wfcmd!
  740.         clr.w   (a1)
  741. hSn_cmdE    addq.l  #2,a1
  742.         clr.w   (a1)+
  743.         clr.l   (a1)+
  744.         clr.l   (a1)+
  745.         clr.l   (a1)+
  746.         move.l  #sinetable,(a1)+
  747.         clr.w   (a1)+
  748.         movea.l trk_synthptr(a5),a0
  749.                 move.w  18(a0),(a1)+
  750.                 clr.b   (a1)
  751.         moveq   #64,d4
  752.         rts
  753.  
  754. synth_start move.w  trk_prevper(a5),d5
  755. synth_start2    move.l  a3,-(sp)    ;d0 = SynthPtr
  756.         move.l  d0,a0
  757.         movea.l trk_audioaddr(a5),a3    ;audio channel base address
  758. ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
  759.         subq.b  #1,trk_volxcnt(a5)  ;decrease execute counter..
  760.         bgt.w   synth_wftbl     ;not 0...go to waveform
  761.         move.b  trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  762.         move.b  trk_volchgspd(a5),d0    ;volume change??
  763.         beq.s   synth_nochgvol      ;no.
  764.         add.b   trk_synvol(a5),d0   ;add previous volume
  765.         bpl.s   synth_voln2l        ;not negative
  766.         moveq   #0,d0           ;was negative => 0
  767. synth_voln2l    cmp.b   #$40,d0         ;too high??
  768.         ble.s   synth_voln2h        ;not 2 high.
  769.         moveq   #$40,d0         ;was 2 high => 64
  770. synth_voln2h    move.b  d0,trk_synvol(a5)   ;remember new...
  771. synth_nochgvol  move.l  trk_envptr(a5),d1   ;envelope pointer
  772.         beq.s   synth_novolenv
  773.         movea.l d1,a1
  774.         move.b  (a1)+,d0
  775.         add.b   #128,d0
  776.         lsr.b   #2,d0
  777.         move.b  d0,trk_synvol(a5)
  778.         addq.b  #1,trk_envcount(a5)
  779.         bpl.s   synth_endenv
  780.         clr.b   trk_envcount(a5)
  781.         move.l  trk_envrestart(a5),a1
  782. synth_endenv    move.l  a1,trk_envptr(a5)
  783. synth_novolenv  move.w  trk_volcmd(a5),d0   ;get table position ptr
  784.         tst.b   trk_volwait(a5)     ;WAI(t) active
  785.         beq.s   synth_getvolcmd     ;no
  786.         subq.b  #1,trk_volwait(a5)  ;yep, decr wait ctr
  787.         ble.s   synth_getvolcmd     ;0 => continue
  788.         bra.w   synth_wftbl     ;> 0 => still wait
  789. synth_inccnt    addq.b  #1,d0
  790. synth_getvolcmd addq.b  #1,d0           ;advance pointer
  791.         move.b  21(a0,d0.w),d1      ;get command
  792.         bmi.s   synth_cmd       ;negative = command
  793.         move.b  d1,trk_synvol(a5)   ;set synthvol
  794.         bra.w   synth_endvol        ;end of volume executing
  795. synth_cmd   and.w   #$000f,d1
  796.         add.b   d1,d1
  797.         move.w  synth_vtbl(pc,d1.w),d1
  798.         jmp syv(pc,d1.w)
  799. synth_vtbl  dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  800.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  801.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  802.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  803.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  804. ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
  805. syv
  806. syv_fe      move.b  22(a0,d0.w),d0      ;JMP
  807.         bra.s   synth_getvolcmd
  808. syv_f0      move.b  22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  809.         bra.s   synth_inccnt
  810. syv_f1      move.b  22(a0,d0.w),trk_volwait(a5) ;WAI(t)
  811.         addq.b  #1,d0
  812.         bra.s   synth_endvol
  813. syv_f3      move.b  22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  814.         bra.s   synth_inccnt
  815. syv_f2      move.b  22(a0,d0.w),d1
  816.         neg.b   d1
  817.         move.b  d1,trk_volchgspd(a5) ;set volume slide down
  818.         bra.s   synth_inccnt
  819. syv_fa      move.b  22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  820.         clr.b   trk_wfwait(a5)
  821.         bra.s   synth_inccnt
  822. syv_f4      move.b  22(a0,d0.w),d1
  823.         bsr.s   synth_getwf
  824.         clr.l   trk_envrestart(a5)
  825. syv_f4end   move.l  a1,trk_envptr(a5)
  826.         clr.b   trk_envcount(a5)
  827.         bra.w   synth_inccnt
  828. syv_f5      move.b  22(a0,d0.w),d1
  829.         bsr.s   synth_getwf
  830.         move.l  a1,trk_envrestart(a5)
  831.         bra.s   syv_f4end
  832. syv_f6      clr.l   trk_envptr(a5)
  833.         bra.w   synth_getvolcmd
  834. synth_getwf ext.w   d1  ;d1 = wform number, returns ptr in a1
  835.         add.w   d1,d1   ;create index
  836.         add.w   d1,d1
  837.         lea 278(a0),a1
  838.         adda.w  d1,a1
  839.         movea.l (a1),a1     ;get wform address
  840.         addq.l  #2,a1       ;skip length
  841.         rts
  842. syv_ff      subq.b  #1,d0
  843. synth_endvol    move.w  d0,trk_volcmd(a5)
  844. synth_wftbl move.b  trk_synvol(a5),trk_prevvol(a5)
  845.         adda.w  #158,a0
  846. ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
  847.         subq.b  #1,trk_wfxcnt(a5)   ;decr. wf speed counter
  848.         bgt.w   synth_arpeggio      ;not yet...
  849.         move.b  trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  850.         move.w  trk_wfcmd(a5),d0    ;get table pos offset
  851.         move.w  trk_wfchgspd(a5),d1 ;CHU/CHD ??
  852.         beq.s   synth_tstwfwai      ;0 = no change
  853. wytanwet    add.w   trk_perchg(a5),d1   ;add value to current change
  854.         move.w  d1,trk_perchg(a5)   ;remember amount of change
  855. synth_tstwfwai  tst.b   trk_wfwait(a5)      ;WAI ??
  856.         beq.s   synth_getwfcmd      ;not waiting...
  857.         subq.b  #1,trk_wfwait(a5)   ;decr wait counter
  858.         beq.s   synth_getwfcmd      ;waiting finished
  859.         bra.w   synth_arpeggio      ;still sleep...
  860. synth_incwfc    addq.b  #1,d0
  861. synth_getwfcmd  addq.b  #1,d0           ;advance position counter
  862.         move.b  -9(a0,d0.w),d1      ;get command
  863.         bmi.s   synth_wfcmd     ;negative = command
  864.         ext.w   d1
  865.         add.w   d1,d1
  866.         add.w   d1,d1
  867.         movea.l 120(a0,d1.w),a1
  868.         move.w  (a1)+,ac_len(a3)    ;push waveform length
  869.         move.l  a1,ac_ptr(a3)       ;and the new pointer
  870.         bra.w   synth_wfend     ;no new commands now...
  871. synth_wfcmd and.w   #$000f,d1       ;get the right nibble
  872.         add.b   d1,d1           ;* 2
  873.         move.w  synth_wfctbl(pc,d1.w),d1
  874.         jmp syw(pc,d1.w)        ;jump to command
  875. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  876.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  877.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  878.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  879. ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
  880. syw
  881. syw_f7      move.b  -8(a0,d0.w),d1
  882.         ext.w   d1
  883.         add.w   d1,d1
  884.         add.w   d1,d1
  885.         movea.l 120(a0,d1.w),a1
  886.         addq.l  #2,a1
  887.         move.l  a1,trk_synvibwf(a5)
  888.         bra.s   synth_incwfc
  889. syw_fe      move.b  -8(a0,d0.w),d0      ;jump (JMP)
  890.         bra.s   synth_getwfcmd
  891. syw_fc      move.w  d0,trk_arpsoffs(a5) ;new arpeggio begin
  892.         move.w  d0,trk_arpgoffs(a5)
  893. synth_findare   addq.b  #1,d0
  894.         tst.b   -9(a0,d0.w)
  895.         bpl.s   synth_findare
  896.         bra.s   synth_getwfcmd
  897. syw_f0      move.b  -8(a0,d0.w),trk_initwfxspd(a5)  ;new waveform speed
  898.         bra synth_incwfc
  899. syw_f1      move.b  -8(a0,d0.w),trk_wfwait(a5)  ;wait waveform
  900.         addq.b  #1,d0
  901.         bra.s   synth_wfend
  902. syw_f4      move.b  -8(a0,d0.w),trk_synvibdep+1(a5) ;set vibrato depth
  903.         bra.w   synth_incwfc
  904. syw_f5      move.b  -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  905.         addq.b  #1,trk_synthvibspd+1(a5)
  906.         bra.w   synth_incwfc
  907. syw_f2      moveq   #0,d1           ;set slide down
  908.         move.b  -8(a0,d0.w),d1
  909. synth_setsld    move.w  d1,trk_wfchgspd(a5)
  910.         bra.w   synth_incwfc
  911. syw_f3      move.b  -8(a0,d0.w),d1      ;set slide up
  912.         neg.b   d1
  913.         ext.w   d1
  914.         bra.s   synth_setsld
  915. syw_f6      clr.w   trk_perchg(a5)      ;reset period
  916.         move.w  trk_prevper(a5),d5
  917.         bra.w   synth_getwfcmd
  918. syw_fa      move.b  -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  919.         clr.b   trk_volwait(a5)
  920.         bra.w   synth_incwfc
  921. syw_ff      subq.b  #1,d0       ;pointer = END - 1
  922. synth_wfend move.w  d0,trk_wfcmd(a5)
  923. ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
  924. synth_arpeggio  move.w  trk_arpgoffs(a5),d0
  925.         beq.s   synth_vibrato
  926.         moveq   #0,d1
  927.         move.b  -8(a0,d0.w),d1
  928.         add.b   trk_prevnote2(a5),d1
  929.         movea.l trk_periodtbl(a5),a1    ;get period table
  930.         add.w   d1,d1
  931.         move.w  0(a1,d1.w),d5
  932.         addq.b  #1,d0
  933.         tst.b   -8(a0,d0.w)
  934.         bpl.s   synth_noarpres
  935.         move.w  trk_arpsoffs(a5),d0
  936. synth_noarpres  move.w  d0,trk_arpgoffs(a5)
  937. ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
  938. synth_vibrato   move.w  trk_synvibdep(a5),d1    ;get vibrato depth
  939.         beq.s   synth_rts       ;0 => no vibrato
  940.         move.w  trk_synviboffs(a5),d0   ;get offset
  941.         lsr.w   #4,d0           ;/ 16
  942.         and.w   #$1f,d0         ;sinetable offset (0-31)
  943.         movea.l trk_synvibwf(a5),a0
  944.         move.b  0(a0,d0.w),d0       ;get a byte
  945.         ext.w   d0          ;to word
  946.         muls    d1,d0           ;amplify (* depth)
  947.         asr.w   #8,d0           ;and divide by 64
  948.         add.w   d0,d5           ;add vibrato...
  949.         move.w  trk_synthvibspd(a5),d0  ;vibrato speed
  950.         add.w   d0,trk_synviboffs(a5)   ;add to offset
  951. synth_rts   add.w   trk_perchg(a5),d5
  952.         cmp.w   #113,d5         ;overflow??
  953.         bge.s   synth_pern2h
  954.         moveq   #113,d1
  955. synth_pern2h    move.l  (sp)+,a3
  956.         rts
  957.     ENDC
  958. sinetable   dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  959.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  960.         dc.b    -106,-90,-71,-49,-25,0
  961.  
  962. _IntHandler:    movem.l d2-d7/a2-a6,-(sp)
  963.     IFNE    CIAB|VBLANK
  964.         movea.l a1,a6   ;get data base address (int_Data)
  965.     ENDC
  966.     IFEQ    CIAB|VBLANK
  967.         lea DB,a6   ;don't expect a1 to contain DB address
  968.     ENDC
  969.         tst.b   bpmcounter-DB(a6)
  970.         bmi.s   plr_nobpm
  971.         subq.b  #1,bpmcounter-DB(a6)
  972.         ble.s   plr_bpmcnt0
  973.         bra.w   plr_exit
  974. plr_bpmcnt0 move.b  #4,bpmcounter-DB(a6)
  975. plr_nobpm   movea.l _module-DB(a6),a2
  976.         move.l  a2,d0
  977.         beq.w   plr_exit
  978.     IFNE    MIDI
  979.         clr.b   lastcmdbyte-DB(a6)  ;no MIDI optimization
  980.     ENDC
  981.         tst.w   mmd_pstate(a2)
  982.         beq.w   plr_exit
  983.     IFNE    MIDI
  984.         clr.l   dmaonmsk-DB(a6)
  985.     ENDC
  986.     IFEQ    MIDI
  987.         clr.w   dmaonmsk-DB(a6)
  988.     ENDC
  989.         movea.l mmd_songinfo(a2),a4
  990.         moveq   #0,d3
  991.         move.b  mmd_counter(a2),d3
  992.         addq.b  #1,d3
  993.         cmp.b   msng_tempo2(a4),d3
  994.         bge.s   plr_pnewnote    ;play new note
  995.         move.b  d3,mmd_counter(a2)
  996.         bne.w   nonewnote   ;do just fx
  997. ; --- new note!!
  998. plr_pnewnote:   clr.b   mmd_counter(a2)
  999.         tst.w   blkdelay-DB(a6)
  1000.         beq.s   plr_noblkdelay
  1001.         subq.w  #1,blkdelay-DB(a6)
  1002.         bne.w   nonewnote
  1003. ; --- now start to play it
  1004. ; -------- GET ADDRESS OF NOTE DATA --------------------------------------
  1005. plr_noblkdelay  move.w  mmd_pblock(a2),d0
  1006.         bsr.w   GetNoteDataAddr
  1007.         moveq   #0,d7       ;number of track
  1008.         moveq   #0,d4
  1009.     IFNE    PLAYMMD0
  1010.         cmp.b   #'1',3(a2)
  1011.         sge d5      ;d5 set -> >= MMD1
  1012.     ENDC
  1013.         lea trackdataptrs-DB(a6),a1
  1014. ; -------- TRACK LOOP (FOR EACH TRACK) -----------------------------------
  1015. plr_loop0:  movea.l (a1)+,a5    ;get address of this track's struct
  1016. ; ---------------- get the note numbers
  1017.         moveq   #0,d3
  1018.     IFNE    PLAYMMD0
  1019.         tst.b   d5
  1020.         bne.s   plr_mmd1_1
  1021.         move.b  (a3)+,d0
  1022.         move.b  (a3),d3
  1023.         addq.l  #2,a3
  1024.         lsr.b   #4,d3
  1025.         bclr    #7,d0
  1026.         beq.s   plr_bseti4
  1027.         bset    #4,d3
  1028. plr_bseti4  bclr    #6,d0
  1029.         beq.s   plr_bseti5
  1030.         bset    #5,d3
  1031. plr_bseti5  move.b  d0,trk_currnote(a5)
  1032.         beq.s   plr_nngok
  1033.         move.b  d0,(a5)
  1034.         bra.s   plr_nngok
  1035. plr_mmd1_1
  1036.     ENDC
  1037.         move.b  (a3)+,d0    ;get the number of this note
  1038.         bpl.s   plr_nothinote
  1039.         moveq   #0,d0
  1040. plr_nothinote   move.b  d0,trk_currnote(a5)
  1041.         beq.s   plr_nosetprevn
  1042.         move.b  d0,(a5)
  1043. plr_nosetprevn  move.b  (a3),d3     ;instrument number
  1044.         addq.l  #3,a3       ;adv. to next track
  1045. ; ---------------- check if there's an instrument number
  1046. plr_nngok   and.w   #$3F,d3
  1047.         beq.s   noinstnum
  1048. ; ---------------- finally, save the number
  1049.         subq.b  #1,d3
  1050.         move.b  d3,trk_previnstr(a5) ;remember instr. number!
  1051. ; ---------------- get the pointer of data's of this sample in Song-struct
  1052.         move.w  d3,d0
  1053.         asl.w   #3,d3
  1054.         lea 0(a4,d3.w),a0   ;a0 contains now address of it
  1055.         move.l  a0,trk_previnstra(a5)
  1056. ; ---------------- get volume
  1057.         move.b  inst_svol(a0),trk_prevvol(a5) ;vol of this instr
  1058.         move.b  inst_strans(a0),trk_stransp(a5)
  1059. ; ---------------- remember some values of this instrument
  1060.         lea holdvals-DB(a6),a0
  1061.         adda.w  d0,a0
  1062.     IFNE    HOLD
  1063.         move.b  (a0),trk_inithold(a5)       ;hold
  1064.         move.b  63(a0),trk_initdecay(a5)    ;decay
  1065.     ENDC
  1066.         move.b  2*63(a0),trk_finetune(a5)   ;finetune
  1067.         move.b  6*63(a0),trk_outputdev(a5)  ;output dev
  1068. ; ---------------- remember transpose
  1069.         clr.w   trk_soffset(a5)     ;sample offset
  1070.         clr.b   trk_miscflags(a5)   ;misc.
  1071. noinstnum   addq.w  #1,d7
  1072.         cmp.w   numtracks-DB(a6),d7
  1073.         blt plr_loop0
  1074.         bsr.w   DoPreFXLoop
  1075. ; -------- NOTE PLAYING LOOP ---------------------------------------------
  1076.         moveq   #0,d7
  1077.         lea trackdataptrs-DB(a6),a1
  1078. plr_loop2   movea.l (a1)+,a5
  1079.         tst.b   trk_fxtype(a5)
  1080.         bne.s   plr_loop2_end
  1081.         move.b  trk_currnote(a5),d1
  1082.         beq.s   plr_loop2_end
  1083. ; ---------------- play
  1084.         move.l  a1,-(sp)
  1085.         ext.w   d1
  1086.         moveq   #0,d3
  1087.         move.b  trk_previnstr(a5),d3    ;instr #
  1088.         movea.l trk_previnstra(a5),a3   ;instr data address
  1089.         move.b  trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1090.         bne.s   plr_nohold0     ;not 0 -> OK
  1091.         st  trk_noteoffcnt(a5)  ;0 -> hold = 0xff (-1)
  1092. ; ---------------- and finally:
  1093. plr_nohold0 bsr _PlayNote       ;play it
  1094.         move.l  (sp)+,a1
  1095. plr_loop2_end   addq.w  #1,d7
  1096.         cmp.w   numtracks-DB(a6),d7
  1097.         blt.s   plr_loop2
  1098. ; -------- THE REST... ---------------------------------------------------
  1099.         bsr.s   AdvSngPtr
  1100. nonewnote   bsr.w   DoFX
  1101. plr_endfx:  bsr _StartDMA   ;turn on DMA
  1102. plr_exit:   movem.l (sp)+,d2-d7/a2-a6
  1103.     IFNE    VBLANK
  1104.         moveq   #0,d0
  1105.     ENDC
  1106.         rts
  1107.  
  1108. ; and advance song pointers
  1109. AdvSngPtr   move.l  mmd_pblock(a2),fxplineblk-DB(a6) ;store pline/block for fx
  1110.         move.w  nextblockline-DB(a6),d1
  1111.         beq.s   plr_advlinenum
  1112.         clr.w   nextblockline-DB(a6)
  1113.         subq.w  #1,d1
  1114.         bra.s   plr_linenumset
  1115. plr_advlinenum  move.w  mmd_pline(a2),d1    ;get current line #
  1116.         addq.w  #1,d1           ;advance line number
  1117. plr_linenumset  cmp.w   numlines-DB(a6),d1  ;advance block?
  1118.         bhi.s   plr_chgblock        ;yes.
  1119.         tst.b   nextblock-DB(a6)    ;command F00/1Dxx?
  1120.         beq.w   plr_nochgblock      ;no, don't change block
  1121. ; -------- CHANGE BLOCK? -------------------------------------------------
  1122. plr_chgblock    tst.b   nxtnoclrln-DB(a6)
  1123.         bne.s   plr_noclrln
  1124.         moveq   #0,d1           ;clear line number
  1125. plr_noclrln tst.w   mmd_pstate(a2)      ;play block or play song
  1126.         bpl.w   plr_nonewseq        ;play block only...
  1127.         cmp.b   #'2',3(a2)      ;MMD2?
  1128.         bne.s   plr_noMMD2_0
  1129. ; ********* BELOW CODE FOR MMD2 ONLY ************************************
  1130. ; -------- CHANGE SEQUENCE -----------------------------------------------
  1131. plr_skipseq move.w  mmd_pseq(a2),d0     ;actually stored as << 2
  1132.         movea.l msng_pseqs(a4),a1   ;ptr to playseqs
  1133.         movea.l 0(a1,d0.w),a0       ;a0 = ptr to curr PlaySeq
  1134.         move.w  mmd_pseqnum(a2),d0  ;get play sequence number
  1135.         tst.b   nextblock-DB(a6)
  1136.         bmi.s   plr_noadvseq        ;Bxx sets nextblock to -1
  1137.         addq.w  #1,d0           ;advance sequence number
  1138. plr_noadvseq    cmp.w   40(a0),d0       ;is this the highest seq number??
  1139.         blt.s   plr_notagain        ;no.
  1140. ; -------- CHANGE SECTION ------------------------------------------------
  1141.         move.w  mmd_psecnum(a2),d0  ;get section number
  1142.         addq.w  #1,d0           ;increase..
  1143.         cmp.w   msng_songlen(a4),d0 ;highest section?
  1144.         blt.s   plr_nohisec
  1145.         moveq   #0,d0           ;yes.
  1146. plr_nohisec move.w  d0,mmd_psecnum(a2)  ;push back.
  1147.         add.w   d0,d0
  1148.         movea.l msng_sections(a4),a0    ;section table
  1149.         move.w  0(a0,d0.w),d0       ;new playseqlist number
  1150.         add.w   d0,d0
  1151.         add.w   d0,d0
  1152.         move.w  d0,mmd_pseq(a2)
  1153.         movea.l 0(a1,d0.w),a0       ;a0 = ptr to new PlaySeq
  1154.         moveq   #0,d0           ;playseq OFFSET = 0
  1155. ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
  1156. plr_notagain    move.w  d0,mmd_pseqnum(a2)  ;remember new playseq pos
  1157.         add.w   d0,d0
  1158.         move.w  42(a0,d0.w),d0      ;get number of the block
  1159.         bpl.s   plr_changeblk   ;neg. values for future expansion
  1160.         bra.s   plr_skipseq ;(skip them)
  1161. ; ********* BELOW CODE FOR MMD0/MMD1 ONLY *******************************
  1162. plr_noMMD2_0    move.w  mmd_pseqnum(a2),d0  ;get play sequence number
  1163.         tst.b   nextblock-DB(a6)
  1164.         bmi.s   plr_noadvseq_b      ;Bxx sets nextblock to -1
  1165.         addq.w  #1,d0           ;advance sequence number
  1166. plr_noadvseq_b  cmp.w   msng_songlen(a4),d0 ;is this the highest seq number??
  1167.         blt.s   plr_notagain_b      ;no.
  1168.         moveq   #0,d0           ;yes: restart song
  1169. plr_notagain_b  move.b  d0,mmd_pseqnum+1(a2)    ;remember new playseq-#
  1170.         lea msng_playseq(a4),a0 ;offset of sequence table
  1171.         move.b  0(a0,d0.w),d0       ;get number of the block
  1172. ; ********* BELOW CODE FOR BOTH FORMATS *********************************
  1173. plr_changeblk
  1174.     IFNE    CHECK
  1175.         cmp.w   msng_numblocks(a4),d0   ;beyond last block??
  1176.         blt.s   plr_nolstblk        ;no..
  1177.         moveq   #0,d0           ;play block 0
  1178.     ENDC
  1179. plr_nolstblk    move.w  d0,mmd_pblock(a2)   ;store block number
  1180. plr_nonewseq    clr.w   nextblock-DB(a6)    ;clear this if F00 set it
  1181. ; ------------------------------------------------------------------------
  1182. plr_nochgblock  move.w  d1,mmd_pline(a2)    ;set new line number
  1183.  
  1184.     IFNE    HOLD
  1185.         lea trackdataptrs-DB(a6),a5
  1186.         move.w  mmd_pblock(a2),d0   ;pblock
  1187.         bsr.w   GetBlockAddr
  1188.         move.w  mmd_pline(a2),d0    ;play line
  1189.         move.b  msng_tempo2(a4),d3  ;interrupts/note
  1190.     IFNE    PLAYMMD0
  1191.         cmp.b   #'1',3(a2)
  1192.         bge.s   plr_mmd1_2
  1193.         move.b  (a0),d7         ;# of tracks
  1194.         move.w  d0,d1
  1195.         add.w   d0,d0   ;d0 * 2
  1196.         add.w   d1,d0   ;+ d0 = d0 * 3
  1197.         mulu    d7,d0
  1198.         lea 2(a0,d0.w),a3
  1199.         subq.b  #1,d7
  1200. plr_chkholdb    movea.l (a5)+,a1        ;track data
  1201.         tst.b   trk_noteoffcnt(a1)  ;hold??
  1202.         bmi.s   plr_holdendb        ;no.
  1203.         move.b  (a3),d1         ;get the 1st byte..
  1204.         bne.s   plr_hold1b
  1205.         move.b  1(a3),d1
  1206.         and.b   #$f0,d1
  1207.         beq.s   plr_holdendb        ;don't hold
  1208.         bra.s   plr_hold2b
  1209. plr_hold1b  and.b   #$3f,d1         ;note??
  1210.         beq.s   plr_hold2b      ;no, cont hold..
  1211.         move.b  1(a3),d1
  1212.         and.b   #$0f,d1         ;get cmd
  1213.         subq.b  #3,d1           ;is there command 3 (slide)
  1214.         bne.s   plr_holdendb        ;no -> end holding
  1215. plr_hold2b  add.b   d3,trk_noteoffcnt(a1)   ;continue holding...
  1216. plr_holdendb    addq.l  #3,a3       ;next note
  1217.         dbf d7,plr_chkholdb
  1218.         rts
  1219. plr_mmd1_2
  1220.     ENDC
  1221.         move.w  (a0),d7     ;# of tracks
  1222.         add.w   d0,d0
  1223.         add.w   d0,d0       ;d0 = d0 * 4
  1224.         mulu    d7,d0
  1225.         lea 8(a0,d0.l),a3
  1226.         subq.b  #1,d7
  1227. plr_chkhold movea.l (a5)+,a1        ;track data
  1228.         tst.b   trk_noteoffcnt(a1)  ;hold??
  1229.         bmi.s   plr_holdend     ;no.
  1230.         move.b  (a3),d1         ;get the 1st byte..
  1231.         bne.s   plr_hold1
  1232.         move.b  1(a3),d0
  1233.         and.b   #$3F,d0
  1234.         beq.s   plr_holdend     ;don't hold
  1235.         bra.s   plr_hold2
  1236. plr_hold1   and.b   #$7f,d1         ;note??
  1237.         beq.s   plr_hold2       ;no, cont hold..
  1238.         move.b  2(a3),d1
  1239.         subq.b  #3,d1           ;is there command 3 (slide)
  1240.         bne.s   plr_holdend     ;no -> end holding
  1241. plr_hold2   add.b   d3,trk_noteoffcnt(a1)   ;continue holding...
  1242. plr_holdend addq.l  #4,a3       ;next note
  1243.         dbf d7,plr_chkhold
  1244.     ENDC
  1245.         rts
  1246.  
  1247. ; *******************************************************************
  1248. ; DoPreFXLoop:  Loop and call DoPreFX
  1249. ; *******************************************************************
  1250. DoPreFXLoop:
  1251. ; -------- PRE-FX COMMAND HANDLING LOOP ----------------------------------
  1252.         moveq   #0,d5   ;command page count
  1253. plr_loop1   move.w  mmd_pblock(a2),d0
  1254.         bsr.w   GetBlockAddr
  1255.         move.w  d5,d1
  1256.         move.w  mmd_pline(a2),d2
  1257.         bsr.w   GetCmdPointer
  1258.         movea.l a0,a3
  1259.         moveq   #0,d7   ;clear track count
  1260.         lea trackdataptrs-DB(a6),a1
  1261. plr_loop1_1 movea.l (a1)+,a5
  1262.         clr.b   trk_fxtype(a5)
  1263.         move.b  (a3),d0         ;command #
  1264.         beq.s   plr_loop1_end
  1265.         moveq   #0,d4
  1266.         move.b  1(a3),d4        ;data byte
  1267.     IFNE    PLAYMMD0
  1268.         cmp.b   #3,d6           ;if adv == 3 -> MMD0
  1269.         bne.s   doprefx_mmd12mask
  1270.         and.w   #$0F,d0
  1271.         bra.s   doprefx_mmd0maskd
  1272. doprefx_mmd12mask
  1273.     ENDC
  1274.         and.w   #$1F,d0
  1275. doprefx_mmd0maskd
  1276.         bsr.s   DoPreFX
  1277.         or.b    d0,trk_fxtype(a5)
  1278. plr_loop1_end   adda.w  d6,a3           ;next track...
  1279.         addq.w  #1,d7
  1280.         cmp.w   numtracks-DB(a6),d7
  1281.         blt.s   plr_loop1_1
  1282.         addq.w  #1,d5
  1283.         cmp.w   numpages-DB(a6),d5
  1284.         bls.s   plr_loop1
  1285.         rts
  1286.  
  1287. ; *******************************************************************
  1288. ; DoPreFX: Perform effects that must be handled before note playing
  1289. ; *******************************************************************
  1290. ; args:     a6 = DB         d0 = command number (w)
  1291. ;       a5 = track data     d5 = note number
  1292. ;       a4 = song       d4 = data
  1293. ;                   d7 = track #
  1294. ; returns:  d0 = 0: play - d0 = 1: don't play
  1295.  
  1296. rtplay      MACRO
  1297.         moveq   #0,d0
  1298.         rts
  1299.         ENDM
  1300. rtnoplay    MACRO
  1301.         moveq   #1,d0
  1302.         rts
  1303.         ENDM
  1304.  
  1305. DoPreFX:    add.b   d0,d0   ;* 2
  1306.         move.w  f_table(pc,d0.w),d0
  1307.         jmp fst(pc,d0.w)
  1308. f_table     dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1309.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  1310.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  1311.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,f_1e-fst,f_1f-fst
  1312. fst
  1313. ; ---------------- tempo (F)
  1314. f_0f        tst.b   d4      ;test effect qual..
  1315.         beq fx0fchgblck ;if effect qualifier (last 2 #'s)..
  1316.         cmp.b   #$f0,d4     ;..is zero, go to next block
  1317.         bhi.s   fx0fspecial ;if it's F1-FF something special
  1318. ; ---------------- just an ordinary "change tempo"-request
  1319.     IFNE    CIAB
  1320.         moveq   #0,d0       ;will happen!!!
  1321.         move.b  d4,d0
  1322.         bsr _SetTempo   ;change The Tempo
  1323.     ENDC
  1324. fx      rtplay
  1325. ; ---------------- no, it was FFx, something special will happen!!
  1326. fx0fspecial:    cmp.b   #$f2,d4
  1327.         beq.s   f_1f
  1328.         cmp.b   #$f4,d4
  1329.         beq.s   f_1f
  1330.         cmp.b   #$f5,d4
  1331.         bne.s   isfxfe
  1332. ; ---------------- FF2 (or 1Fxx)
  1333. f_1f
  1334.     IFNE    HOLD
  1335.         move.b  trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1336.         bne.s   f_1frts         ;not 0 -> OK
  1337.         st  trk_noteoffcnt(a5)  ;0 -> hold = 0xff (-1)
  1338.     ENDC
  1339. f_1frts     rtnoplay
  1340. isfxfe:     cmp.b   #$fe,d4
  1341.         bne.s   notcmdfe
  1342. ; ---------------- it was FFE, stop playing
  1343.         clr.w   mmd_pstate(a2)
  1344.     IFNE    CIAB
  1345.         movea.l craddr-DB(a6),a0
  1346.         bclr    #0,(a0)
  1347.     ENDC
  1348.         bsr.w   SoundOff
  1349.     IFNE    AURA
  1350.         jsr _RemAura(pc)
  1351.     ENDC
  1352.         adda.w  #8,sp   ;2 subroutine levels
  1353.         bra.w   plr_exit
  1354. f_ffe_no8   rtplay
  1355. notcmdfe:   cmp.b   #$fd,d4 ;change period
  1356.         bne.s   isfxff
  1357. ; ---------------- FFD, change the period, don't replay the note
  1358.     IFNE    CHECK
  1359.         cmp.w   #4,d7 ;no tracks above 4, thank you!!
  1360.         bge.s   f_ff_rts
  1361.     ENDC
  1362.         move.l  trk_periodtbl(a5),d1    ;period table
  1363.         beq.s   f_1frts
  1364.         movea.l d1,a0
  1365.         move.b  trk_currnote(a5),d0
  1366.         subq.b  #1,d0    ;sub 1 to make "real" note number
  1367.     IFNE    CHECK
  1368.         bmi.s   f_1frts
  1369.     ENDC
  1370.         add.b   msng_playtransp(a4),d0
  1371.         add.b   trk_stransp(a5),d0
  1372.         add.w   d0,d0
  1373.         bmi.s   f_1frts
  1374.         move.w  0(a0,d0.w),trk_prevper(a5) ;get & push the period
  1375.         rtnoplay
  1376. isfxff:     cmp.b   #$ff,d4     ;note off??
  1377.         bne.s   f_ff_rts
  1378.         move.w  d7,d0
  1379.         move.l  a1,-(sp)
  1380.         bsr.w   _ChannelOff
  1381.         move.l  (sp)+,a1
  1382. f_ff_rts    rtplay
  1383. ; ---------------- F00, called Pattern Break in ST
  1384. fx0fchgblck:    move.b  #1,nextblock-DB(a6) ;next block????...YES!!!! (F00)
  1385.         bra.s   f_ff_rts
  1386. ; ---------------- was not Fxx, then it's something else!!
  1387. f_0e
  1388.     IFNE    CHECK
  1389.         cmp.b   #4,d7
  1390.         bge.s   f_0e_rts
  1391.     ENDC
  1392.         bset    #0,trk_miscflags(a5)
  1393.         move.b  d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  1394. f_0e_rts    rtplay
  1395. ; ---------------- change volume
  1396. f_0c        move.b  d4,d0
  1397.         bpl.s   plr_nosetdefvol
  1398.         and.b   #$7F,d0
  1399.     IFNE    CHECK
  1400.         cmp.b   #64,d0
  1401.         bgt.s   go_nocmd
  1402.     ENDC
  1403.         moveq   #0,d1
  1404.         move.b  trk_previnstr(a5),d1
  1405.         asl.w   #3,d1
  1406.         move.b  d0,inst_svol(a4,d1.w)   ;set new svol
  1407.         bra.s   plr_setvol
  1408. plr_nosetdefvol btst    #4,msng_flags(a4)   ;look at flags
  1409.         bne.s   volhex
  1410.         lsr.b   #4,d0       ;get number from left
  1411.         mulu    #10,d0      ;number of tens
  1412.         move.b  d4,d1       ;get again
  1413.         and.b   #$0f,d1     ;this time don't get tens
  1414.         add.b   d1,d0       ;add them
  1415. volhex:
  1416.     IFNE    CHECK
  1417.         cmp.b   #64,d0
  1418.         bhi.s   go_nocmd
  1419.     ENDC
  1420. plr_setvol  move.b  d0,trk_prevvol(a5)
  1421. go_nocmd    rtplay
  1422. ; ---------------- tempo2 change??
  1423. f_09
  1424.     IFNE    CHECK
  1425.         and.b   #$1F,d4
  1426.         bne.s   fx9chk
  1427.         moveq   #$20,d4
  1428.     ENDC
  1429. fx9chk:     move.b  d4,msng_tempo2(a4)
  1430. f_09_rts    rtplay
  1431. ; ---------------- block delay
  1432. f_1e        tst.w   blkdelay-DB(a6)
  1433.         bne.s   f_1e_rts
  1434.         addq.w  #1,d4
  1435.         move.w  d4,blkdelay-DB(a6)
  1436. f_1e_rts    rtplay
  1437. ; ---------------- finetune
  1438. f_15
  1439.     IFNE    CHECK
  1440.         cmp.b   #7,d4
  1441.         bgt.s   f_15_rts
  1442.         cmp.b   #-8,d4
  1443.         blt.s   f_15_rts
  1444.     ENDC
  1445.         move.b  d4,trk_finetune(a5)
  1446. f_15_rts    rtplay
  1447. ; ---------------- repeat loop
  1448. f_16        tst.b   d4
  1449.         bne.s   plr_dorpt
  1450.         move.w  mmd_pline(a2),rptline-DB(a6)
  1451.         bra.s   f_16_rts
  1452. plr_dorpt   tst.w   rptcounter-DB(a6)
  1453.         beq.s   plr_newrpt
  1454.         subq.w  #1,rptcounter-DB(a6)
  1455.         beq.s   f_16_rts
  1456.         bra.s   plr_setrptline
  1457. plr_newrpt  move.b  d4,rptcounter+1-DB(a6)
  1458. plr_setrptline  move.w  rptline-DB(a6),d0
  1459.         addq.w  #1,d0
  1460.         move.w  d0,nextblockline-DB(a6)
  1461. f_16_rts    rtplay
  1462. ; ---------------- preset change
  1463. f_1c        cmp.b   #$80,d4
  1464.         bhi.s   f_1c_rts
  1465.         moveq   #0,d1
  1466.         move.b  trk_previnstr(a5),d1
  1467.         add.w   d1,d1
  1468.         lea ext_midipsets-DB(a6),a0
  1469.         ext.w   d4
  1470.         move.w  d4,0(a0,d1.w)       ;set MIDI preset
  1471. f_1c_rts    rtplay
  1472. ; ---------------- note off time set??
  1473. f_08
  1474.     IFNE    HOLD
  1475.         move.b  d4,d0
  1476.         lsr.b   #4,d4       ;extract left  nibble
  1477.         and.b   #$0f,d0     ; "   "  right  "  "
  1478.         move.b  d4,trk_initdecay(a5)    ;left = decay
  1479.         move.b  d0,trk_inithold(a5) ;right = hold
  1480.     ENDC
  1481.         rtplay
  1482. ; ---------------- sample begin offset
  1483. f_19        lsl.w   #8,d4
  1484.         move.w  d4,trk_soffset(a5)
  1485. f_19_rts    rtplay
  1486. ; ---------------- cmd Bxx, "position jump"
  1487. f_0b
  1488.     IFNE    CHECK
  1489.         cmp.b   #'2',3(a2)
  1490.         beq.s   chk0b_mmd2
  1491.         cmp.w   msng_songlen(a4),d4
  1492.         bhi.s   f_0b_rts
  1493.         bra.s   chk0b_end
  1494. chk0b_mmd2  move.w  mmd_pseq(a2),d0     ;get seq number
  1495.         movea.l msng_pseqs(a4),a0   ;ptr to playseqs
  1496.         movea.l 0(a0,d0.w),a0       ;a0 = ptr to curr PlaySeq
  1497.         cmp.w   40(a0),d4       ;test song length
  1498.         bhi.s   f_0b_rts
  1499. chk0b_end
  1500.     ENDC
  1501.         move.w  d4,mmd_pseqnum(a2)
  1502.         st  nextblock-DB(a6)    ; = 1
  1503. f_0b_rts    rtplay
  1504. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1505. f_1d        move.w  #$1ff,nextblock-DB(a6)
  1506.         addq.w  #1,d4
  1507.         move.w  d4,nextblockline-DB(a6)
  1508.         rtplay
  1509. ; ---------------- try portamento (3)
  1510. f_03
  1511.     IFNE    CHECK
  1512.         cmp.w   #4,d7
  1513.         bge.s   f_03_rts
  1514.     ENDC
  1515.         moveq   #0,d0
  1516.         move.b  trk_currnote(a5),d0
  1517.         subq.b  #1,d0       ;subtract note number
  1518.         bmi.s   plr_setfx3spd   ;0 -> set new speed
  1519.         move.l  trk_periodtbl(a5),d1
  1520.         beq.s   f_03_rts
  1521.         movea.l d1,a0
  1522.         add.b   msng_playtransp(a4),d0  ;play transpose
  1523.         add.b   trk_stransp(a5),d0 ;and instrument transpose
  1524.         bmi.s   f_03_rts    ;again.. too low
  1525.         add.w   d0,d0
  1526.         move.w  0(a0,d0.w),trk_porttrgper(a5) ;period of this note is the target
  1527. plr_setfx3spd:  tst.b   d4      ;qual??
  1528.         beq.s   f_03_rts    ;0 -> do nothing
  1529.         move.b  d4,trk_prevportspd(a5)  ;store speed
  1530. f_03_rts    rtnoplay
  1531.  
  1532. ; *******************************************************************
  1533. ; DoFX: Handle effects, hold/fade etc.
  1534. ; *******************************************************************
  1535. DoFX        moveq   #0,d3
  1536.         move.b  mmd_counter(a2),d3
  1537.     IFNE    HOLD
  1538.         lea trackdataptrs-DB(a6),a1
  1539. ; Loop 1: Hold/Fade handling
  1540.         moveq   #0,d7   ;clear track count
  1541. dofx_loop1  movea.l (a1)+,a5
  1542.         bsr.w   HoldAndFade
  1543.         addq.w  #1,d7
  1544.         cmp.w   numtracks-DB(a6),d7
  1545.         blt.s   dofx_loop1
  1546.     ENDC
  1547. ; Loop 2: Track command handling
  1548.         moveq   #0,d5   ;command page count
  1549. dofx_loop2  move.w  fxplineblk-DB(a6),d0
  1550.         bsr.w   GetBlockAddr
  1551.         movea.l a0,a3
  1552.     IFNE    PLAYMMD0
  1553.         cmp.b   #'1',3(a2)
  1554.         bge.s   dofx_sbd_nommd0
  1555.         bsr.w   StoreBlkDimsMMD0
  1556.         bra.s   dofx_sbd_mmd0
  1557. dofx_sbd_nommd0
  1558.     ENDC
  1559.         bsr.w   StoreBlockDims
  1560. dofx_sbd_mmd0   move.w  d5,d1
  1561.         move.w  fxplineblk+2-DB(a6),d2
  1562.         movea.l a3,a0
  1563.         bsr.s   GetCmdPointer
  1564.         movea.l a0,a3
  1565.         moveq   #0,d7   ;clear track count
  1566.         lea trackdataptrs-DB(a6),a1
  1567. dofx_loop2_1    movea.l (a1)+,a5
  1568.         moveq   #0,d4
  1569.         move.b  (a3),d0         ;command #
  1570.         move.b  1(a3),d4        ;data byte
  1571.     IFNE    PLAYMMD0
  1572.         cmp.b   #3,d6           ;if adv == 3 -> MMD0
  1573.         bne.s   dofx_mmd12mask
  1574.         and.w   #$0F,d0
  1575.         bra.s   dofx_mmd0maskd
  1576. dofx_mmd12mask
  1577.     ENDC
  1578.         and.w   #$1F,d0
  1579. dofx_mmd0maskd  tst.b   trk_fxtype(a5)
  1580.         bgt.s   dofx_lend2_1    ;1 = skip
  1581.     IFNE    MIDI
  1582.         beq.s   dofx_chfx
  1583.         bsr.w   MIDIFX
  1584.         bra.s   dofx_lend2_1
  1585.     ENDC
  1586.     IFEQ    MIDI
  1587.         bne.s   dofx_lend2_1
  1588.     ENDC
  1589. dofx_chfx   bsr.w   ChannelFX
  1590. dofx_lend2_1    adda.w  d6,a3           ;next track...
  1591.         addq.w  #1,d7
  1592.         cmp.w   numtracks-DB(a6),d7
  1593.         blt.s   dofx_loop2_1
  1594.         addq.w  #1,d5
  1595.         cmp.w   numpages-DB(a6),d5
  1596.         bls.s   dofx_loop2
  1597. ; Loop 3: Updating audio hardware
  1598.         moveq   #0,d7   ;clear track count
  1599.         lea trackdataptrs-DB(a6),a1
  1600. dofx_loop3  movea.l (a1)+,a5
  1601.     IFNE    HOLD
  1602.         tst.b   trk_fxtype(a5)
  1603.         bne.s   dofx_lend3  ;only in case 0 (norm)
  1604.     ENDC
  1605.     IFEQ    HOLD
  1606.         cmp.w   #4,d7
  1607.         bge.s   dofx_stopl3
  1608.     ENDC
  1609.         bsr.w   UpdatePerVol
  1610. dofx_lend3  addq.w  #1,d7
  1611.         cmp.w   numtracks-DB(a6),d7
  1612.         blt.s   dofx_loop3
  1613. dofx_stopl3 rts
  1614.  
  1615. ; *******************************************************************
  1616. ; GetCmdPointer: Return command pointer for track 0
  1617. ; *******************************************************************
  1618. ; args:     a0 = block pointer
  1619. ;       d1 = page number
  1620. ;       d2 = line number
  1621. ;       a2 = module
  1622. ; result:   a0 = command pointer (i.e. trk 0 note + 2)
  1623. ;       d6 = track advance (bytes)
  1624. ; scratches:    d0, d1, d2, a0
  1625. ; Note: no num_pages check! If numpages > 0 it can be assumed that
  1626. ; extra pages exist.
  1627.  
  1628. GetCmdPointer
  1629.     IFNE    PLAYMMD0
  1630.         cmp.b   #'1',3(a2)
  1631.         blt.s   GetCmdPtrMMD0
  1632.     ENDC
  1633.         mulu    (a0),d2     ;d2 = line # * numtracks
  1634.         add.l   d2,d2       ;d2 *= 2...
  1635.         subq.w  #1,d1
  1636.         bmi.s   gcp_page0
  1637.         movea.l 4(a0),a0
  1638.         movea.l 12(a0),a0
  1639.         add.w   d1,d1
  1640.         add.w   d1,d1
  1641.         movea.l 4(a0,d1.w),a0   ;command data
  1642.         adda.l  d2,a0
  1643.         moveq   #2,d6
  1644.         rts
  1645. gcp_page0   add.l   d2,d2       ;d2 *= 4
  1646.         lea 10(a0,d2.l),a0  ;offs: 4 = header, 2 = note
  1647.         moveq   #4,d6       ;track advance (bytes)
  1648.         rts
  1649.     IFNE    PLAYMMD0
  1650. GetCmdPtrMMD0   moveq   #0,d0
  1651.         move.b  (a0),d0     ;get numtracks
  1652.         mulu    d0,d2       ;line # * numtracks
  1653.         move.w  d2,d0
  1654.         add.w   d2,d2
  1655.         add.w   d0,d2       ; *= 3...
  1656.         lea 3(a0,d2.l),a0   ;offs: 2 = header, 1 = note
  1657.         moveq   #3,d6
  1658.         rts
  1659.     ENDC
  1660.  
  1661. ; *******************************************************************
  1662. ; GetBlockAddr: Return pointer to block
  1663. ; *******************************************************************
  1664. ; args:     d0 = block number
  1665. ; result:   a0 = block pointer
  1666. ; scratches: d0, a0
  1667.  
  1668. GetBlockAddr    movea.l mmd_blockarr(a2),a0
  1669.         add.w   d0,d0
  1670.         add.w   d0,d0
  1671.         movea.l 0(a0,d0.w),a0
  1672.         rts
  1673.  
  1674. ; *******************************************************************
  1675. ; GetNoteDataAddr: Check & return addr. of current note
  1676. ; *******************************************************************
  1677. ;args:      d0 = pblock     a6 = DB
  1678. ;returns:   a3 = address
  1679. ;scratches: d0, a0, d1
  1680.  
  1681. GetNoteDataAddr bsr.w   GetBlockAddr
  1682.         movea.l a0,a3
  1683.     IFNE    PLAYMMD0
  1684.         cmp.b   #'1',3(a2)
  1685.         blt.s   GetNDAddrMMD0
  1686.     ENDC
  1687.         bsr.w   StoreBlockDims
  1688.         move.w  numlines-DB(a6),d1
  1689.         move.w  mmd_pline(a2),d0
  1690.         cmp.w   d1,d0       ;check if block end exceeded...
  1691.         bls.s   plr_nolinex
  1692.         move.w  d1,d0
  1693. plr_nolinex add.w   d0,d0
  1694.         add.w   d0,d0   ;d0 = d0 * 4
  1695.         mulu    numtracks-DB(a6),d0
  1696.         lea 8(a3,d0.l),a3   ;address of current note
  1697.         rts
  1698.  
  1699.     IFNE    PLAYMMD0
  1700. GetNDAddrMMD0   bsr.w   StoreBlkDimsMMD0
  1701.         move.w  numlines-DB(a6),d1
  1702.         move.w  mmd_pline(a2),d0
  1703.         cmp.w   d1,d0       ;check if block end exceeded...
  1704.         bls.s   plr_nolinex2
  1705.         move.w  d1,d0
  1706. plr_nolinex2    move.w  d0,d1
  1707.         add.w   d0,d0
  1708.         add.w   d1,d0   ;d0 = d0 * 3
  1709.         mulu    numtracks-DB(a6),d0
  1710.         lea 2(a3,d0.l),a3   ;address of current note
  1711.         rts
  1712.     ENDC
  1713.  
  1714. ; *******************************************************************
  1715. ; StoreBlockDims: Store block dimensions
  1716. ; *******************************************************************
  1717. ; args:     a0 = block ptr, a6 = DB
  1718.  
  1719. StoreBlockDims  move.l  (a0)+,numtracks-DB(a6)  ;numtracks & lines
  1720.         tst.l   (a0)            :BlockInfo
  1721.         beq.s   sbd_1page
  1722.         movea.l (a0),a0
  1723.         move.l  12(a0),d0       ;BlockInfo.pagetable
  1724.         beq.s   sbd_1page
  1725.         movea.l d0,a0
  1726.         move.w  (a0),numpages-DB(a6)    ;num_pages
  1727.         rts
  1728. sbd_1page   clr.w   numpages-DB(a6)
  1729.         rts
  1730.  
  1731.     IFNE    PLAYMMD0
  1732. StoreBlkDimsMMD0
  1733.         clr.w   numpages-DB(a6)
  1734.         moveq   #0,d0
  1735.         move.b  (a0)+,d0        ;numtracks
  1736.         move.w  d0,numtracks-DB(a6)
  1737.         move.b  (a0),d0         ;numlines
  1738.         move.w  d0,numlines-DB(a6)
  1739.         rts
  1740.     ENDC
  1741.  
  1742. ; *******************************************************************
  1743. ; HoldAndFade: Handle hold/fade
  1744. ; *******************************************************************
  1745. ; args:     a5 = track data
  1746. ;       a6 = DB
  1747. ;       d7 = track #
  1748. ; scratches:    d0, d1, a0
  1749.  
  1750.     IFNE    HOLD
  1751. HoldAndFade
  1752.     IFNE    MIDI
  1753.         tst.b   trk_prevmidin(a5)   ;is it MIDI??
  1754.         bne.w   plr_haf_midi
  1755.     ENDC
  1756.     IFNE    CHECK
  1757.         cmp.w   #4,d7
  1758.         bge.w   plr_haf_midi    ;no non-MIDI effects in tracks 4 - 15
  1759.     ENDC
  1760.         tst.b   trk_noteoffcnt(a5)
  1761.         bmi.s   plr_haf_noholdexp
  1762.         subq.b  #1,trk_noteoffcnt(a5)
  1763.         bpl.s   plr_haf_noholdexp
  1764.     IFNE    SYNTH
  1765.         tst.b   trk_synthtype(a5)       ;synth/hybrid??
  1766.         beq.s   plr_nosyndec
  1767.         move.b  trk_decay(a5),trk_volcmd+1(a5)  ;set volume command pointer
  1768.         clr.b   trk_volwait(a5)         ;abort WAI
  1769.         bra.s   plr_haf_noholdexp
  1770.     ENDC
  1771. plr_nosyndec    move.b  trk_decay(a5),trk_fadespd(a5)   ;set fade...
  1772.         bne.s   plr_haf_noholdexp       ;if > 0, don't stop sound
  1773.         moveq   #0,d0
  1774.         bset    d7,d0
  1775.         move.w  d0,$dff096          ;shut DMA...
  1776. plr_haf_noholdexp
  1777.         move.b  trk_fadespd(a5),d0  ;fade??
  1778.         beq.s   plr_haf_dofx        ;no.
  1779.         sub.b   d0,trk_prevvol(a5)
  1780.         bpl.s   plr_nofade2low
  1781.         clr.b   trk_prevvol(a5)
  1782.         clr.b   trk_fadespd(a5)     ;fade no more
  1783. plr_nofade2low
  1784. plr_haf_dofx    clr.b   trk_fxtype(a5)
  1785. plr_haf_rts rts
  1786. ; MIDI version
  1787. plr_haf_midi
  1788.     IFNE    MIDI
  1789.         st  trk_fxtype(a5)
  1790.         tst.b   trk_noteoffcnt(a5)
  1791.         bmi.s   plr_haf_rts
  1792.         subq.b  #1,trk_noteoffcnt(a5)
  1793.         bpl.s   plr_haf_rts
  1794.         move.b  trk_prevmidin(a5),d1
  1795.         beq.s   plr_haf_rts
  1796.         lea noteondata-DB(a6),a0
  1797.         exg.l   a5,a1
  1798.         bsr.w   choff_midi
  1799.         exg.l   a5,a1
  1800.     ENDC
  1801.         rts
  1802. ;hold
  1803.     ENDC
  1804.  
  1805. ; *******************************************************************
  1806. ; ChannelFX:    Do an effect on a channel
  1807. ; *******************************************************************
  1808. ;args:                  d3 = counter
  1809. ;       a4 = song struct    d4 = command qual (long, byte used)
  1810. ;       a5 = track data ptr 
  1811. ;       a6 = DB         d0 = command (long, byte used)
  1812. ;                   d7 = track (channel) number
  1813. ;scratches: d0, d1, d4, a0
  1814.  
  1815. ChannelFX   add.b   d0,d0   ;* 2
  1816.         move.w  fx_table(pc,d0.w),d0
  1817.         jmp fxs(pc,d0.w)
  1818. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1819.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1820.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
  1821.         dc.w    fx_0f-fxs
  1822.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1823.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1824.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1825.         dc.w    fx_1f-fxs
  1826. fxs:
  1827. ;   **************************************** Effect 01 ******
  1828. fx_01       tst.b   d3
  1829.         bne.s   fx_01nocnt0
  1830.         btst    #5,msng_flags(a4)   ;FLAG_STSLIDE??
  1831.         bne.s   fx_01rts
  1832. fx_01nocnt0 move.w  trk_prevper(a5),d0
  1833.         sub.w   d4,d0
  1834.         cmp.w   #113,d0
  1835.         bge.s   fx_01noovf
  1836.         move.w  #113,d0
  1837. fx_01noovf  move.w  d0,trk_prevper(a5)
  1838. fx_xx       ;fx_xx is just a RTS
  1839. fx_01rts    rts
  1840. ;   **************************************** Effect 11 ******
  1841. fx_11       tst.b   d3
  1842.         bne.s   fx_11rts
  1843.         sub.w   d4,trk_prevper(a5)
  1844. fx_11rts    rts
  1845. ;   **************************************** Effect 02 ******
  1846. fx_02       tst.b   d3
  1847.         bne.s   fx_02nocnt0
  1848.         btst    #5,msng_flags(a4)
  1849.         bne.s   fx_02rts
  1850. fx_02nocnt0 add.w   d4,trk_prevper(a5)
  1851. fx_02rts    rts
  1852. ;   **************************************** Effect 12 ******
  1853. fx_12       tst.b   d3
  1854.         bne.s   fx_12rts
  1855.         add.w   d4,trk_prevper(a5)
  1856. fx_12rts    rts
  1857. ;   **************************************** Effect 00 ******
  1858. fx_00       tst.b   d4  ;both fxqualifiers are 0s: no arpeggio
  1859.         beq.s   fx_00rts
  1860.         move.l  d3,d0
  1861.         divu    #3,d0
  1862.         swap    d0
  1863.         subq.b  #1,d0
  1864.         bgt.s   fx_arp2
  1865.         blt.s   fx_arp0
  1866.         and.b   #$0f,d4
  1867.         bra.s   fx_doarp
  1868. fx_arp0     lsr.b   #4,d4
  1869.         bra.s   fx_doarp
  1870. fx_arp2     moveq   #0,d4
  1871. fx_doarp:   move.b  (a5),d0
  1872.         subq.b  #1,d0       ;-1 to make it 0 - 127
  1873.         add.b   msng_playtransp(a4),d0  ;add play transpose
  1874.         add.b   trk_stransp(a5),d0  ;add instrument transpose
  1875.         add.b   d0,d4
  1876.         move.l  trk_periodtbl(a5),d1
  1877.         beq.s   fx_00rts
  1878.         movea.l d1,a0
  1879.         add.b   d0,d0
  1880.         move.w  0(a0,d0.w),d0   ;base note period
  1881.         add.b   d4,d4
  1882.         sub.w   0(a0,d4.w),d0   ;calc difference from base note
  1883.         move.w  d0,trk_arpadjust(a5)
  1884. fx_00rts    rts
  1885. ;   **************************************** Effect 04 ******
  1886. fx_14       move.b  #6,trk_vibshift(a5)
  1887.         bra.s   vib_cont
  1888. fx_04       move.b  #5,trk_vibshift(a5)
  1889. vib_cont    tst.b   d3
  1890.         bne.s   nonvib
  1891.         move.b  d4,d1
  1892.         beq.s   nonvib
  1893.         and.w   #$0f,d1
  1894.         beq.s   plr_chgvibspd
  1895.         move.w  d1,trk_vibrsz(a5)
  1896. plr_chgvibspd   and.b   #$f0,d4
  1897.         beq.s   nonvib
  1898.         lsr.b   #3,d4
  1899.         and.b   #$3e,d4
  1900.         move.b  d4,trk_vibrspd(a5)
  1901. nonvib      move.b  trk_vibroffs(a5),d0
  1902.         lsr.b   #2,d0
  1903.         and.w   #$1f,d0
  1904.         moveq   #0,d1
  1905.         lea sinetable(pc),a0
  1906.         move.b  0(a0,d0.w),d0
  1907.         ext.w   d0
  1908.         muls    trk_vibrsz(a5),d0
  1909.         move.b  trk_vibshift(a5),d1
  1910.         asr.w   d1,d0
  1911.         move.w  d0,trk_vibradjust(a5)
  1912.         move.b  trk_vibrspd(a5),d0
  1913.         add.b   d0,trk_vibroffs(a5)
  1914. fx_04rts    rts
  1915. ;   **************************************** Effect 06 ******
  1916. fx_06:      tst.b   d3
  1917.         bne.s   fx_06nocnt0
  1918.         btst    #5,msng_flags(a4)
  1919.         bne.s   fx_04rts
  1920. fx_06nocnt0 bsr.s   plr_volslide        ;Volume slide
  1921.         bra.s   nonvib          ;+ Vibrato
  1922. ;   **************************************** Effect 07 ******
  1923. fx_07       tst.b   d3
  1924.         bne.s   nontre
  1925.         move.b  d4,d1
  1926.         beq.s   nontre
  1927.         and.w   #$0f,d1
  1928.         beq.s   plr_chgtrespd
  1929.         move.w  d1,trk_tremsz(a5)
  1930. plr_chgtrespd   and.b   #$f0,d4
  1931.         beq.s   nontre
  1932.         lsr.b   #2,d4
  1933.         and.b   #$3e,d4
  1934.         move.b  d4,trk_tremspd(a5)
  1935. nontre      move.b  trk_tremoffs(a5),d0
  1936.         lsr.b   #3,d0
  1937.         and.w   #$1f,d0
  1938.         lea sinetable(pc),a0
  1939.         move.b  0(a0,d0.w),d1
  1940.         ext.w   d1
  1941.         muls    trk_tremsz(a5),d1
  1942.         asr.w   #7,d1
  1943.         move.b  trk_tremspd(a5),d0
  1944.         add.b   d0,trk_tremoffs(a5)
  1945.         add.b   trk_prevvol(a5),d1
  1946.         bpl.s   tre_pos
  1947.         moveq   #0,d1
  1948. tre_pos     cmp.b   #64,d1
  1949.         ble.s   tre_no2hi
  1950.         moveq   #64,d1
  1951. tre_no2hi   move.b  d1,trk_tempvol(a5)
  1952.         rts
  1953. ;   ********* VOLUME SLIDE FUNCTION *************************
  1954. plr_volslide    move.b  d4,d0
  1955.         moveq   #0,d1
  1956.         move.b  trk_prevvol(a5),d1 ;move previous vol to d1
  1957.         and.b   #$f0,d0
  1958.         bne.s   crescendo
  1959.         sub.b   d4,d1   ;sub from prev. vol
  1960. voltest0    bpl.s   novolover64
  1961.         moveq   #0,d1   ;volumes under zero not accepted
  1962.         bra.s   novolover64
  1963. crescendo:  lsr.b   #4,d0
  1964.         add.b   d0,d1
  1965. voltest     cmp.b   #64,d1
  1966.         ble.s   novolover64
  1967.         moveq   #64,d1
  1968. novolover64 move.b  d1,trk_prevvol(a5)
  1969. volsl_rts   rts
  1970. ;   **************************************** Effect 0D/0A ***
  1971. fx_0a:
  1972. fx_0d:      tst.b   d3
  1973.         bne.s   plr_volslide
  1974.         btst    #5,msng_flags(a4)
  1975.         beq.s   plr_volslide
  1976.         rts
  1977. ;   **************************************** Effect 05 ******
  1978. fx_05:      tst.b   d3
  1979.         bne.s   fx_05nocnt0
  1980.         btst    #5,msng_flags(a4)
  1981.         bne.s   fx_05rts
  1982. fx_05nocnt0 bsr.s   plr_volslide
  1983.         bra.s   fx_03nocnt0
  1984. fx_05rts    rts
  1985. ;   **************************************** Effect 1A ******
  1986. fx_1a       tst.b   d3
  1987.         bne.s   volsl_rts
  1988.         move.b  trk_prevvol(a5),d1
  1989.         add.b   d4,d1
  1990.         bra.s   voltest
  1991. ;   **************************************** Effect 1B ******
  1992. fx_1b       tst.b   d3
  1993.         bne.s   volsl_rts
  1994.         move.b  trk_prevvol(a5),d1
  1995.         sub.b   d4,d1
  1996.         bra.s   voltest0
  1997. ;   **************************************** Effect 03 ******
  1998. fx_03       tst.b   d3
  1999.         bne.s   fx_03nocnt0
  2000.         btst    #5,msng_flags(a4)
  2001.         bne.s   fx_03rts
  2002. fx_03nocnt0 move.w  trk_porttrgper(a5),d0   ;d0 = target period
  2003.         beq.s   fx_03rts
  2004.         move.w  trk_prevper(a5),d1  ;d1 = curr. period
  2005.         move.b  trk_prevportspd(a5),d4  ;get prev. speed
  2006.         cmp.w   d0,d1
  2007.         bhi.s   subper  ;curr. period > target period
  2008.         add.w   d4,d1   ;add the period
  2009.         cmp.w   d0,d1
  2010.         bge.s   targreached
  2011.         bra.s   targnreach
  2012. subper:     sub.w   d4,d1   ;subtract
  2013.         cmp.w   d0,d1   ;compare current period to target period
  2014.         bgt.s   targnreach
  2015. targreached:    move.w  trk_porttrgper(a5),d1 ;eventually push target period
  2016.         clr.w   trk_porttrgper(a5) ;now we can forget everything
  2017. targnreach: move.w  d1,trk_prevper(a5)
  2018. fx_03rts    rts
  2019. ;   **************************************** Effect 13 ******
  2020. fx_13:      cmp.b   #3,d3
  2021.         bge.s   fx_13rts    ;if counter < 3
  2022.         neg.w   d4
  2023.         move.w  d4,trk_vibradjust(a5)   ;subtract effect qual...
  2024. fx_13rts    rts
  2025. ;   *********************************************************
  2026. fx_0c:      tst.b   d3
  2027.         bne.s   fx_13rts
  2028. dvc_0       move.b  trk_prevvol(a5),d1
  2029.         rts
  2030. ;   **************************************** Effect 10 ******
  2031. fx_10:
  2032.     IFNE    MIDI
  2033.         tst.b   d3
  2034.         bne.s   fx_13rts
  2035.         move.w  d4,d0
  2036.         bra.w   _InitMIDIDump
  2037.     ENDC
  2038.     IFEQ    MIDI
  2039.         rts
  2040.     ENDC
  2041. ;   **************************************** Effect 18 ******
  2042. fx_18       cmp.b   d4,d3
  2043.         bne.s   fx_18rts
  2044.         clr.b   trk_prevvol(a5)
  2045. fx_18rts    rts
  2046. ;   **************************************** Effect 1F ******
  2047. fx_1f       move.b  d4,d1
  2048.         lsr.b   #4,d4       ;note delay
  2049.         beq.s   nonotedelay
  2050.         cmp.b   d4,d3       ;compare to counter
  2051.         blt.s   fx_18rts    ;tick not reached
  2052.         bne.s   nonotedelay
  2053.         bra playfxnote  ;trigger note
  2054. nonotedelay and.w   #$0f,d1     ;retrig?
  2055.         beq.s   fx_18rts
  2056.         moveq   #0,d0
  2057.         move.b  d3,d0
  2058.         divu    d1,d0
  2059.         swap    d0      ;get modulo of counter/tick
  2060.         tst.w   d0
  2061.         bne.s   fx_18rts
  2062.         bra playfxnote  ;retrigger
  2063. ;   **************************************** Effect 0F ******
  2064. ;   see below...
  2065. ;   *********************************************************
  2066.  
  2067. ; *******************************************************************
  2068. ; UpdatePerVol: Update audio registers (period & volume) after FX
  2069. ; *******************************************************************
  2070. ; args:     a6 = DB         d7 = channel #
  2071. ;       a5 = track data
  2072. ; scratches:    d0, d1, a0, d5
  2073. UpdatePerVol    move.w  trk_prevper(a5),d5
  2074.     IFNE    SYNTH
  2075.         move.l  trk_synthptr(a5),d0
  2076.         beq.s   plr_upv_nosynth
  2077.         move.l  a1,-(sp)
  2078.         bsr.w   synth_start
  2079.         move.l  (sp)+,a1
  2080.     ENDC
  2081. plr_upv_nosynth add.w   trk_vibradjust(a5),d5
  2082.         sub.w   trk_arpadjust(a5),d5
  2083.         clr.l   trk_vibradjust(a5)  ;clr both adjusts
  2084.         movea.l trk_audioaddr(a5),a0
  2085.         move.w  d5,ac_per(a0)       ;push period
  2086.         moveq   #0,d0
  2087.         move.b  trk_tempvol(a5),d0
  2088.         bpl.s   plr_upv_setvol
  2089.         move.b  trk_prevvol(a5),d0
  2090. plr_upv_setvol  st  trk_tempvol(a5)
  2091. ; -------- GetRelVol: Calculate track volume -----------------------------
  2092. ; track # = d7, note vol = d0, song = a4
  2093.     IFNE    RELVOL
  2094.         mulu    trk_trackvol(a5),d0 ;d0 = master v. * track v. * volume
  2095.         lsr.w   #8,d0
  2096.     ENDC
  2097.         move.b  d0,ac_vol+1(a0)
  2098.         rts
  2099.  
  2100. ; **** a separate routine for handling command 0F
  2101. fx_0f       cmp.b   #$f1,d4
  2102.         bne.s   no0ff1
  2103.         cmp.b   #3,d3
  2104.         beq.s   playfxnote
  2105.         rts
  2106. no0ff1:     cmp.b   #$f2,d4
  2107.         bne.s   no0ff2
  2108.         cmp.b   #3,d3
  2109.         beq.s   playfxnote
  2110.         rts
  2111. no0ff2:     cmp.b   #$f3,d4
  2112.         bne.s   no0ff3
  2113.         move.b  d3,d0
  2114.         beq.s   cF_rts
  2115.         and.b   #1,d0       ;is 2 or 4
  2116.         bne.s   cF_rts
  2117. playfxnote: moveq   #0,d1
  2118.         move.b  trk_currnote(a5),d1 ;get note # of curr. note
  2119.         beq.s   cF_rts
  2120.         move.b  trk_noteoffcnt(a5),d0   ;get hold counter
  2121.         bmi.s   pfxn_nohold     ;no hold, or hold over
  2122.         add.b   d3,d0           ;increase by counter val
  2123.         bra.s   pfxn_hold
  2124. pfxn_nohold move.b  trk_inithold(a5),d0 ;get initial hold
  2125.         bne.s   pfxn_hold
  2126.         st  d0
  2127. pfxn_hold   move.b  d0,trk_noteoffcnt(a5)
  2128.         movem.l a1/a3/d3/d6,-(sp)
  2129.         moveq   #0,d3
  2130.         move.b  trk_previnstr(a5),d3    ;and prev. sample #
  2131.         movea.l trk_previnstra(a5),a3
  2132.         bsr _PlayNote
  2133. pndone_0ff  movem.l (sp)+,a1/a3/d3/d6
  2134. cF_rts      rts
  2135. no0ff3:     cmp.b   #$f4,d4     ;triplet cmd 1
  2136.         bne.s   no0ff4
  2137.         moveq   #0,d0
  2138.         move.b  msng_tempo2(a4),d0
  2139.         divu    #3,d0
  2140.         cmp.b   d0,d3
  2141.         beq.s   playfxnote
  2142.         rts
  2143. no0ff4      cmp.b   #$f5,d4     ;triplet cmd 2
  2144.         bne.s   no0ff5
  2145.         moveq   #0,d0
  2146.         move.b  msng_tempo2(a4),d0
  2147.         divu    #3,d0
  2148.         add.w   d0,d0
  2149.         cmp.b   d0,d3
  2150.         beq.s   playfxnote
  2151.         rts
  2152. no0ff5      cmp.b   #$f8,d4     ;f8 = filter off
  2153.         beq.s   plr_filteroff
  2154.         cmp.b   #$f9,d4     ;f9 = filter on
  2155.         bne.s   cF_rts
  2156.         bclr    #1,$bfe001
  2157.         bset    #0,msng_flags(a4)
  2158.         rts
  2159. plr_filteroff:  bset    #1,$bfe001
  2160.         bclr    #0,msng_flags(a4)
  2161.         rts
  2162.  
  2163. ; -------- HANDLE DMA WAIT (PROCESSOR-INDEPENDENT) -----------------------
  2164. _Wait1line: move.w  d0,-(sp)
  2165. wl0:        move.b  $dff007,d0
  2166. wl1:        cmp.b   $dff007,d0
  2167.         beq.s   wl1
  2168.         dbf d1,wl0
  2169.         move.w  (sp)+,d0
  2170.         rts
  2171. pushnewvals:    movea.l (a1)+,a5
  2172.         lsr.b   #1,d0
  2173.         bcc.s   rpnewv
  2174.         move.l  trk_sampleptr(a5),d1
  2175.         beq.s   rpnewv
  2176.         movea.l trk_audioaddr(a5),a0
  2177.         move.l  d1,ac_ptr(a0)
  2178.         move.w  trk_samplelen(a5),ac_len(a0)
  2179. rpnewv:     rts
  2180.  
  2181. ; -------- AUDIO DMA ROUTINE ---------------------------------------------
  2182. _StartDMA:  ;This small routine turns on audio DMA
  2183.         move.w  dmaonmsk-DB(a6),d0  ;dmaonmsk contains the mask of
  2184.         beq.s   sdma_nodmaon    ;the channels that must be turned on
  2185.         bset    #15,d0  ;DMAF_SETCLR: set these bits in dmacon
  2186.         moveq   #80,d1
  2187. ; The following line makes the playroutine one scanline slower. If your
  2188. ; song works well without the following instruction, you can leave it out.
  2189.     IFNE    SYNTH
  2190.         add.w   d1,d1   ;sometimes double wait time is required
  2191.     ENDC
  2192.         bsr.s   _Wait1line
  2193.         move.w  d0,$dff096  ;do that!!!
  2194.         moveq   #80,d1
  2195.         bsr.s   _Wait1line
  2196.         lea trackdataptrs-DB(a6),a1
  2197.         bsr.s   pushnewvals
  2198.         bsr.s   pushnewvals
  2199.         bsr.s   pushnewvals
  2200.     IFNE    MIDI
  2201.         bsr.s   pushnewvals
  2202.     ENDC
  2203.     IFEQ    MIDI
  2204.         bra.s   pushnewvals
  2205.     ENDC
  2206. sdma_nodmaon
  2207.     IFNE    MIDI
  2208.         lea bytesinnotebuff-DB(a6),a0
  2209.         move.w  (a0)+,d0
  2210.         beq.s   rpnewv
  2211.         bra.w   _AddMIDId
  2212.     ENDC
  2213.         rts
  2214.  
  2215. _SetTempo:
  2216.     IFNE    CIAB
  2217.         move.l  _module-DB(a6),d1
  2218.         beq.s   ST_x
  2219.         move.l  d1,a0
  2220.         movea.l mmd_songinfo(a0),a0
  2221.         btst    #5,msng_flags2(a0)
  2222.         bne.s   ST_bpm
  2223.         cmp.w   #10,d0  ;If tempo <= 10, use SoundTracker tempo
  2224.         bhi.s   calctempo
  2225.         subq.b  #1,d0
  2226.         add.w   d0,d0
  2227.         move.w  sttempo+2(pc,d0.w),d1
  2228.         bra.s   pushtempo
  2229. calctempo:  move.l  timerdiv-DB(a6),d1
  2230.         divu    d0,d1
  2231. pushtempo:  movea.l craddr+4-DB(a6),a0
  2232.         move.b  d1,(a0)     ;and set the CIA timer
  2233.         lsr.w   #8,d1
  2234.         movea.l craddr+8-DB(a6),a0
  2235.         move.b  d1,(a0)
  2236.     ENDC
  2237. ST_x        rts ;   vv-- These values are the SoundTracker tempos (approx.)
  2238. sttempo:    dc.w    $0f00
  2239.     IFNE    CIAB
  2240.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  2241. ST_bpm      move.b  msng_flags2(a0),d1
  2242.         and.w   #$1F,d1
  2243.         addq.b  #1,d1
  2244.         mulu    d1,d0
  2245.         move.l  bpmdiv-DB(a6),d1
  2246.         divu    d0,d1
  2247.         bra.s   pushtempo
  2248.     ENDC
  2249.  
  2250.     IFNE    MIDI
  2251. MIDIFX      add.b   d0,d0   ;* 2
  2252.         move.w  midicmd_table(pc,d0.w),d0
  2253.         jmp midifx(pc,d0.w)
  2254. midicmd_table   dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  2255.         dc.w    mfx_05-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2256.         dc.w    mfx_0a-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_0d-midifx,mfx_0e-midifx
  2257.         dc.w    mfx_0f-midifx
  2258.         dc.w    mfx_10-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_13-midifx
  2259.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_17-midifx
  2260.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2261.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_1f-midifx
  2262. midifx      
  2263. mfx_01      lea prevmidipbend-DB(a6),a0
  2264.         moveq   #0,d1
  2265.         move.b  trk_prevmidich(a5),d1   ;get previous midi channel
  2266.         add.b   d1,d1       ;UWORD index
  2267.         tst.b   d4      ;x100??
  2268.         beq.s   resetpbend
  2269.         move.w  0(a0,d1.w),d0   ;get previous pitch bend
  2270.         lsl.w   #3,d4       ;multiply bend value by 8
  2271.         add.w   d4,d0
  2272.         cmp.w   #$3fff,d0
  2273.         bls.s   bendpitch
  2274.         move.w  #$3fff,d0
  2275. bendpitch:  move.w  d0,0(a0,d1.w)   ;save current pitch bend
  2276.         lsr.b   #1,d1       ;back to UBYTE
  2277.         or.b    #$e0,d1
  2278.         lea noteondata-DB(a6),a0
  2279.         move.b  d1,(a0)     ;midi command & channel
  2280.         move.b  d0,1(a0)    ;lower value
  2281.         and.b   #$7f,1(a0)  ;clear bit 7
  2282.         lsr.w   #7,d0
  2283.         and.b   #$7f,d0     ;clr bit 7
  2284.         move.b  d0,2(a0)    ;higher 7 bits
  2285.         moveq   #3,d0
  2286.         bra.w   _AddMIDId
  2287.  
  2288. mfx_02      lea prevmidipbend-DB(a6),a0
  2289.         moveq   #0,d1
  2290.         move.b  trk_prevmidich(a5),d1
  2291.         add.b   d1,d1
  2292.         tst.b   d4
  2293.         beq.s   resetpbend  ;x200??
  2294.         move.w  0(a0,d1.w),d0
  2295.         lsl.w   #3,d4
  2296.         sub.w   d4,d0
  2297.         bpl.s   bendpitch   ;not under 0
  2298.         moveq   #0,d0
  2299.         bra.s   bendpitch
  2300. resetpbend: tst.b   d3      ;d3 = counter (remember??)
  2301.         bne.s   mfx_rts
  2302.         move.w  #$2000,d0
  2303.         bra.s   bendpitch
  2304. mfx_rts     rts
  2305. mfx_13
  2306. mfx_03      tst.b   d3
  2307.         bne.s   mfx_rts
  2308.         lea prevmidipbend-DB(a6),a0
  2309.         moveq   #0,d1
  2310.         move.b  trk_prevmidich(a5),d1
  2311.         add.b   d1,d1
  2312.         move.b  d4,d0
  2313.         add.b   #128,d0
  2314.         lsl.w   #6,d0
  2315.         bra.s   bendpitch
  2316.  
  2317. mfx_0d      tst.b   d3
  2318.         bne.s   mfx_rts
  2319.         lea noteondata+1-DB(a6),a0  ;CHANNEL AFTERTOUCH
  2320.         move.b  d4,(a0) ;value
  2321.         bmi.s   mfx_rts
  2322.         move.b  trk_prevmidich(a5),-(a0)
  2323.         or.b    #$d0,(a0)
  2324.         moveq   #2,d0
  2325.         bra.w   _AddMIDId
  2326.  
  2327. mfx_0a      tst.b   d3
  2328.         bne.s   mfx_rts
  2329.         lea noteondata+2-DB(a6),a0  ;POLYPHONIC AFTERTOUCH
  2330.         and.b   #$7f,d4
  2331.         move.b  d4,(a0)
  2332.         move.b  trk_prevmidin(a5),-(a0)
  2333.         ble.s   mfx_rts
  2334.         move.b  trk_prevmidich(a5),-(a0)
  2335.         or.b    #$A0,(a0)
  2336.         moveq   #3,d0
  2337.         bra.w   _AddMIDId
  2338.  
  2339. mfx_17      moveq   #$07,d0     ;07 = VOLUME
  2340.         bra.s   pushctrldata
  2341.  
  2342. mfx_04      moveq   #$01,d0     ;01 = MODULATION WHEEL
  2343.         bra.s   pushctrldata
  2344.  
  2345. mfx_0e      moveq   #$0a,d0
  2346. pushctrldata    tst.b   d3      ;do it only once in a note
  2347.         bne.s   mfx_rts2    ;(when counter = 0)
  2348.         lea noteondata+2-DB(a6),a0 ;push "control change" data,
  2349.         move.b  d4,(a0)     ;second databyte
  2350.         bmi.s   mfx_rts2    ;$0 - $7F only
  2351.         move.b  d0,-(a0)    ;1st databyte
  2352.         move.b  trk_prevmidich(a5),-(a0)    ;MIDI channel
  2353.         or.b    #$b0,(a0)   ;command (B)
  2354.         moveq   #3,d0
  2355.         bra.w   _AddMIDId
  2356.  
  2357. mfx_05      and.b   #$7f,d4     ;set contr. value of curr. MIDI ch.
  2358.         move.b  trk_prevmidich(a5),d6
  2359.         lea midicontrnum-DB(a6),a0
  2360.         adda.w  d6,a0
  2361.         move.b  d4,(a0)
  2362. mfx_rts2    rts
  2363.  
  2364. mfx_0f      cmp.b   #$fa,d4     ;hold pedal ON
  2365.         bne.s   nomffa
  2366.         moveq   #$40,d0
  2367.         moveq   #$7f,d4
  2368.         bra.s   pushctrldata
  2369. nomffa      cmp.b   #$fb,d4     ;hold pedal OFF
  2370.         bne.w   fx_0f
  2371.         moveq   #$40,d0
  2372.         moveq   #$00,d4
  2373.         bra.s   pushctrldata
  2374.  
  2375. mfx_00      tst.b   d4
  2376.         beq.s   mfx_rts2
  2377.         and.b   #$7f,d4
  2378.         move.b  trk_prevmidich(a5),d6
  2379.         lea midicontrnum-DB(a6),a0
  2380.         move.b  0(a0,d6.w),d0
  2381.         bra.s   pushctrldata
  2382.  
  2383. mfx_10      tst.b   d3
  2384.         bne.s   mfx_rts3
  2385.         move.w  d4,d0
  2386.         bra.w   _InitMIDIDump
  2387.  
  2388. mfx_1f      move.b  d4,d1
  2389.         lsr.b   #4,d4       ;note delay
  2390.         beq.s   nonotedelay_m
  2391.         cmp.b   d4,d3       ;compare to counter
  2392.         blt.s   mfx_rts3    ;tick not reached
  2393.         bne.s   nonotedelay_m
  2394.         bsr playfxnote  ;trigger note
  2395. nonotedelay_m   and.w   #$0f,d1     ;retrig?
  2396.         beq.s   mfx_rts3
  2397.         moveq   #0,d0
  2398.         move.b  d3,d0
  2399.         divu    d1,d0
  2400.         swap    d0      ;get modulo of counter/tick
  2401.         tst.w   d0
  2402.         beq playfxnote
  2403. mfx_rts3    rts
  2404.  
  2405. _ResetMIDI: movem.l d2/a2/a6,-(sp)
  2406.         movea.l 4.w,a6      ;ExecBase
  2407.         jsr -$78(a6)    ;Disable()
  2408.         lea DB,a6
  2409. ; Clear preset memory
  2410.         lea prevmidicpres-DB(a6),a0
  2411.         moveq   #7,d2
  2412. RM_loop0    clr.l   (a0)+   ;force presets to be set again
  2413.         dbf d2,RM_loop0
  2414.         clr.b   lastcmdbyte
  2415. ; Reset pitchbenders & modulation wheels
  2416.         lea midiresd-DB(a6),a2
  2417.         move.b  #$e0,(a2)
  2418.         move.b  #$b0,3(a2)
  2419.         moveq   #15,d2
  2420. respbendl:  movea.l a2,a0
  2421.         moveq   #6,d0
  2422.         bsr.w   _AddMIDId
  2423.         addq.b  #1,(a2)
  2424.         addq.b  #1,3(a2)
  2425.         dbf d2,respbendl
  2426.         lea prevmidipbend-DB(a6),a2
  2427.         moveq   #15,d2
  2428. resprevpbends:  move.w  #$2000,(a2)+
  2429.         dbf d2,resprevpbends
  2430. ; Clear dump variables
  2431.         clr.b   sysx-DB(a6)
  2432.         lea dumpqueue-DB(a6),a0
  2433.         move.l  a0,dqreadptr-DB(a6)
  2434.         move.l  a0,dqwriteptr-DB(a6)
  2435.         clr.w   dqentries-DB(a6)
  2436. ; Enable & exit
  2437.         movea.l 4.w,a6
  2438.         jsr -$7e(a6)    ;Enable()
  2439.         movem.l (sp)+,d2/a2/a6
  2440.         rts
  2441.     ENDC
  2442.  
  2443. ; *************************************************************************
  2444. ; *************************************************************************
  2445. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2446. ; *************************************************************************
  2447. ; *************************************************************************
  2448.  
  2449.     IFEQ    EASY
  2450.         XDEF    _InitModule,_PlayModule
  2451.         XDEF    _InitPlayer,_RemPlayer,_StopPlayer
  2452.         XDEF    _ContModule
  2453.     ENDC
  2454.  
  2455. ; *************************************************************************
  2456. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  2457. ; *************************************************************************
  2458.  
  2459. _InitModule:    movem.l a2-a3/d2,-(sp)
  2460.         move.l  a0,-(sp)
  2461.         beq IM_exit         ;0 => xit
  2462.     IFNE    RELVOL    
  2463.         movea.l mmd_songinfo(a0),a1 ;MMD0song
  2464.         move.b  msng_mastervol(a1),d0   ;d0 = mastervol
  2465.         ext.w   d0
  2466.         lea trackdataptrs,a2
  2467.         cmp.b   #'2',3(a0)      ;MMD2?
  2468.         bne.s   IM_mmd01
  2469.         move.w  msng_numtracks(a1),d1
  2470.         subq.w  #1,d1
  2471.         movea.l msng_trkvoltbl(a1),a1
  2472.         bra.s   IM_loop0
  2473. IM_mmd01    lea msng_trkvol(a1),a1  ;a1 = trkvol
  2474.         moveq   #MAX_MMD1_TRACKS-1,d1
  2475. IM_loop0    move.b  (a1)+,d2    ;get vol...
  2476.         ext.w   d2
  2477.         move.l  (a2)+,a3    ;pointer to track data
  2478.         mulu    d0,d2       ;mastervol * trackvol
  2479.         lsr.w   #4,d2
  2480.         move.w  d2,trk_trackvol(a3)
  2481.         dbf d1,IM_loop0
  2482.     ENDC
  2483.     IFNE    SYNTH
  2484.         lea trackdataptrs,a2
  2485.         moveq   #3,d1
  2486. IM_loop1    move.l  (a2)+,a3
  2487.         clr.l   trk_synthptr(a3)
  2488.         clr.b   trk_synthtype(a3)
  2489.         dbf d1,IM_loop1
  2490.     ENDC
  2491.         lea holdvals,a2
  2492.         movea.l a0,a3
  2493.         move.l  mmd_expdata(a0),d0  ;expdata...
  2494.     IFEQ    MIDI
  2495.         beq.s   IM_clrhlddec        ;none here
  2496.     ENDC
  2497.     IFNE    MIDI
  2498.         beq.w   IM_clrhlddec
  2499.     ENDC
  2500.         move.l  d0,a1
  2501.         move.l  4(a1),d0        ;exp_smp
  2502.     IFEQ    MIDI
  2503.         beq.s   IM_clrhlddec    ;again.. nothing
  2504.     ENDC
  2505.     IFNE    MIDI
  2506.         beq.w   IM_clrhlddec
  2507.     ENDC
  2508.         move.l  d0,a0       ;InstrExt...
  2509.         move.w  8(a1),d2    ;# of entries
  2510.     IFEQ    MIDI
  2511.         beq.s   IM_clrhlddec
  2512.     ENDC
  2513.     IFNE    MIDI
  2514.         beq.w   IM_clrhlddec
  2515.     ENDC
  2516.         subq.w  #1,d2       ;-1 (for dbf)
  2517.         move.w  10(a1),d0   ;entry size
  2518.         movea.l mmd_songinfo(a3),a3 ;MMD0song
  2519.     IFNE    MIDI
  2520.         lea 4*63(a2),a1 ;pointer to ext_midipsets...
  2521.     ENDC
  2522. IM_loop2    clr.b   2*63(a2)        ;clear finetune
  2523.         cmp.w   #3,d0
  2524.         ble.s   IM_noftune
  2525.         move.b  3(a0),126(a2)   ;InstrExt.finetune -> finetune
  2526. IM_noftune  clr.b   3*63(a2)    ;clear flags
  2527.         cmp.w   #6,d0
  2528.         blt.s   IM_noflags
  2529.         move.b  5(a0),3*63(a2)  ;InstrExt.flags -> flags
  2530.         bra.s   IM_gotflags
  2531. IM_noflags  cmp.w   #1,inst_replen(a3)
  2532.         bls.s   IM_gotflags
  2533.         bset    #0,3*63(a2)
  2534. IM_gotflags clr.b   6*63(a2)    ;Initally OUTPUT_STD
  2535.         cmp.w   #9,d0
  2536.         blt.s   IM_noopdev
  2537.         move.b  8(a0),6*63(a2)  ;get InstrExt.output_device
  2538.     IFNE    AURA
  2539.         cmp.b   #1,8(a0)    ;is it OUTPUT_AURA?
  2540.         bne.s   IM_noopdev
  2541. ; does no harm to call several times...
  2542.         jsr _InitAura(pc)
  2543.     ENDC
  2544. IM_noopdev
  2545.     IFNE    MIDI
  2546.         cmp.w   #2,d0
  2547.         ble.s   IM_nsmnoff
  2548.         tst.b   2(a0)       ;suppress MIDI note off?
  2549.         beq.s   IM_nsmnoff
  2550.         bset    #7,inst_midich(a3)
  2551. IM_nsmnoff  move.b  inst_midipreset(a3),d1
  2552.         ext.w   d1
  2553.         move.w  d1,(a1)
  2554.         cmp.w   #8,d0
  2555.         ble.s   IM_nolongpset
  2556.         move.w  6(a0),(a1)  ;-> ext_midipsets
  2557.         btst    #1,5(a0)
  2558.         beq.s   IM_nolongpset
  2559.         bset    #6,inst_midich(a3)
  2560. IM_nolongpset   addq.l  #2,a1
  2561.     ENDC
  2562.         move.b  1(a0),63(a2)    ;InstrExt.decay -> decay
  2563.         move.b  (a0),(a2)+  ;InstrExt.hold -> holdvals
  2564.         adda.w  d0,a0       ;ptr to next InstrExt
  2565.         addq.l  #8,a3       ;next instrument...
  2566.         dbf d2,IM_loop2
  2567.         bra.s   IM_exit
  2568. IM_clrhlddec    move.w  #3*63-1,d0  ;no InstrExt => clear holdvals/decays
  2569. IM_loop3    clr.w   (a2)+       ;..and finetunes/flags/ext_psets
  2570.         dbf d0,IM_loop3
  2571.         movea.l (sp),a0
  2572. ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
  2573. ; -------- also copy inst_midipreset to ext_midipsets.
  2574.         movea.l mmd_songinfo(a0),a3
  2575.         lea flags,a2
  2576.     IFNE    MIDI
  2577.         lea ext_midipsets,a1
  2578.     ENDC
  2579.         moveq   #62,d0
  2580. IM_loop4    cmp.w   #1,inst_replen(a3)
  2581.         bls.s   IM_noreptflg
  2582.         bset    #0,(a2)
  2583. IM_noreptflg    addq.l  #1,a2
  2584.     IFNE    MIDI
  2585.         move.b  inst_midipreset(a3),d1
  2586.         ext.w   d1
  2587.         move.w  d1,(a1)+
  2588.     ENDC
  2589.         addq.l  #8,a3       ;next inst
  2590.         dbf d0,IM_loop4
  2591. IM_exit     addq.l  #4,sp
  2592.         movem.l (sp)+,a2-a3/d2
  2593.         rts
  2594. ; *************************************************************************
  2595. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  2596. ; *************************************************************************
  2597. _InitPlayer:
  2598.     IFNE    MIDI
  2599.         bsr.w   _GetSerial
  2600.         tst.l   d0
  2601.         bne.s   IP_error
  2602.     ENDC
  2603.         bsr.w   _AudioInit
  2604.         tst.l   d0
  2605.         bne.s   IP_error
  2606.         rts
  2607. IP_error    bsr.s   _RemPlayer
  2608.         moveq   #-1,d0
  2609.         rts
  2610. ; *************************************************************************
  2611. ; RemPlayer() -- free interrupt, audio, serial port etc..
  2612. ; *************************************************************************
  2613. _RemPlayer:
  2614.     move.b  _timeropen,d0
  2615.         beq.s   RP_notimer  ;timer is not ours
  2616.         bsr.s   _StopPlayer
  2617. RP_notimer:
  2618.     bsr.w   _AudioRem
  2619.     IFNE    MIDI
  2620.         bra.w   _FreeSerial
  2621.     ELSEIF
  2622.         rts
  2623.     ENDC
  2624. ; *************************************************************************
  2625. ; StopPlayer() -- stop the music
  2626. ; *************************************************************************
  2627. _StopPlayer:    lea DB,a1
  2628.         move.b  _timeropen-DB(a1),d0
  2629.         beq.s   SP_end      ;res. alloc fail.
  2630.     IFNE    CIAB
  2631.         movea.l craddr-DB(a1),a0
  2632.         bclr    #0,(a0)     ;stop timer
  2633.     ENDC
  2634.     IFNE    AURA
  2635.         jsr _RemAura(pc)
  2636.     ENDC
  2637.         move.l  _module-DB(a1),d0
  2638.         beq.s   SP_nomod
  2639.         move.l  d0,a0
  2640.         clr.w   mmd_pstate(a0)
  2641.         clr.l   _module-DB(a1)
  2642. SP_nomod
  2643.     IFNE    MIDI
  2644.         clr.b   lastcmdbyte-DB(a1)
  2645.     ENDC
  2646.         bra.w   SoundOff
  2647. SP_end      rts
  2648.  
  2649.  
  2650. _ContModule tst.b   _timeropen
  2651.         beq.s   SP_end
  2652.         movea.l craddr,a1
  2653.         bclr    #0,(a1)
  2654.         move.l  a0,-(sp)
  2655.         bsr.w   SoundOff
  2656.         move.l  (sp)+,a0
  2657.         moveq   #0,d0
  2658.         bra.s   contpoint
  2659. ; *************************************************************************
  2660. ; PlayModule(a0 = module)  -- initialize & play it!
  2661. ; *************************************************************************
  2662. _PlayModule:    st  d0
  2663. contpoint   movem.l a0/d0,-(sp)
  2664.         bsr _InitModule
  2665.         movem.l (sp)+,a0/d0
  2666.         move.l  a6,-(sp)
  2667.         lea DB,a6
  2668.         tst.b   _timeropen-DB(a6)
  2669.         beq PM_end      ;resource allocation failure
  2670.         move.l  a0,d1
  2671.         beq PM_end      ;module failure
  2672.     IFNE    CIAB
  2673.         movea.l craddr-DB(a6),a1
  2674.         bclr    #0,(a1)     ;stop timer...
  2675.     ENDC
  2676.         clr.l   _module-DB(a6)
  2677.     IFNE    MIDI
  2678.         clr.b   lastcmdbyte-DB(a6)
  2679.     ENDC
  2680.         move.w  _modnum,d1
  2681.         beq.s   PM_modfound
  2682. PM_nextmod  tst.l   mmd_expdata(a0)
  2683.         beq.s   PM_modfound
  2684.         move.l  mmd_expdata(a0),a1
  2685.         tst.l   (a1)
  2686.         beq.s   PM_modfound     ;no more modules here!
  2687.         move.l  (a1),a0
  2688.         subq.w  #1,d1
  2689.         bgt.s   PM_nextmod
  2690. PM_modfound cmp.b   #'T',3(a0)
  2691.         bne.s   PM_nomodT
  2692.         move.b  #'0',3(a0)  ;change MCNT to MCN0
  2693. PM_nomodT   movea.l mmd_songinfo(a0),a1     ;song
  2694.         move.b  msng_tempo2(a1),mmd_counter(a0) ;init counter
  2695.         btst    #0,msng_flags(a1)
  2696.         bne.s   PM_filon
  2697.         bset    #1,$bfe001
  2698.         bra.s   PM_filset
  2699. PM_filon    bclr    #1,$bfe001
  2700. PM_filset   tst.b   d0
  2701.         beq.s   PM_noclr
  2702.         clr.l   mmd_pline(a0)
  2703.         clr.l   rptline-DB(a6)
  2704.         clr.w   blkdelay-DB(a6)
  2705. ; ---------- Set 'pblock' and 'pseq' to correct values...
  2706. PM_noclr    cmp.b   #'2',3(a0)
  2707.         bne.s   PM_oldpbset
  2708.         move.w  mmd_psecnum(a0),d1
  2709.         move.l  a2,-(sp)        ;need extra register
  2710.         movea.l msng_sections(a1),a2
  2711.         add.w   d1,d1
  2712.         move.w  0(a2,d1.w),d1       ;get sequence number
  2713.         add.w   d1,d1
  2714.         add.w   d1,d1
  2715.         move.w  d1,mmd_pseq(a0)
  2716.         movea.l msng_pseqs(a1),a2
  2717.         movea.l 0(a2,d1.w),a2       ;PlaySeq...
  2718.         move.w  mmd_pseqnum(a0),d1
  2719.         add.w   d1,d1
  2720.         move.w  42(a2,d1.w),d1      ;and the correct block..
  2721.         move.l  (sp)+,a2
  2722.         bra.s   PM_setblk
  2723. PM_oldpbset move.w  mmd_pseqnum(a0),d1
  2724.         add.w   #msng_playseq,d1
  2725.         move.b  0(a1,d1.w),d1       ;get first playseq entry
  2726.         ext.w   d1
  2727. PM_setblk   move.w  d1,mmd_pblock(a0)
  2728.         move.w  #-1,mmd_pstate(a0)
  2729.         move.l  a0,_module-DB(a6)
  2730.         btst    #5,msng_flags2(a1)  ;BPM?
  2731.         seq bpmcounter-DB(a6)
  2732.     IFNE    CIAB
  2733.         move.w  msng_deftempo(a1),d0    ;get default tempo
  2734.         movea.l craddr-DB(a6),a1
  2735.         bsr.w   _SetTempo   ;set default tempo
  2736.         bset    #0,(a1)     ;start timer => PLAY!!
  2737.     ENDC
  2738. PM_end      move.l  (sp)+,a6
  2739.         rts
  2740. ; *************************************************************************
  2741.  
  2742. _AudioInit: movem.l a4/a6/d2-d3,-(sp)
  2743.         lea DB,a4
  2744.         moveq   #0,d2
  2745.         movea.l 4.w,a6
  2746. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  2747.     IFNE    AUDDEV
  2748.         moveq   #1,d2
  2749.         moveq   #-1,d0
  2750.         jsr -$14a(a6)   ;AllocSignal()
  2751.         tst.b   d0
  2752.         bmi.w   initerr
  2753.         move.b  d0,sigbitnum-DB(a4)
  2754. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  2755.         lea allocport-DB(a4),a1
  2756.         move.b  d0,15(a1)   ;set mp_SigBit
  2757.         move.l  a1,-(sp)
  2758.         suba.l  a1,a1
  2759.         jsr -$126(a6)   ;FindTask(0)
  2760.         move.l  (sp)+,a1
  2761.         move.l  d0,16(a1)   ;set mp_SigTask
  2762.         lea reqlist-DB(a4),a0
  2763.         move.l  a0,(a0)     ;NEWLIST begins...
  2764.         addq.l  #4,(a0)
  2765.         clr.l   4(a0)
  2766.         move.l  a0,8(a0)    ;NEWLIST ends...
  2767. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  2768.         moveq   #2,d2
  2769.         lea allocreq-DB(a4),a1
  2770.         lea audiodevname-DB(a4),a0
  2771.         moveq   #0,d0
  2772.         moveq   #0,d1
  2773.         movea.l 4.w,a6
  2774.         jsr -$1bc(a6)   ;OpenDevice()
  2775.         tst.b   d0
  2776.         bne.w   initerr
  2777.         st  audiodevopen-DB(a4)
  2778. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open cia resource
  2779.         moveq   #3,d2
  2780.     ENDC
  2781.     IFNE    CIAB
  2782.         cmp.b   #50,$212(a6)    ;ExecBase->VBlankFrequency
  2783.         beq.s   init_pal
  2784.         move.l  #474326,timerdiv-DB(a4) ;Assume that CIA freq is 715 909 Hz
  2785.         move.l  #3579545/2,bpmdiv-DB(a4)
  2786. init_pal    moveq   #0,d3
  2787.         lea cianame-DB(a4),a1
  2788.         move.b  #'a',3(a1)
  2789. open_ciares moveq   #0,d0
  2790.         jsr -$1f2(a6)   ;OpenResource()
  2791.         move.l  d0,_ciaresource
  2792.         beq.s   try_CIAB
  2793.         moveq   #4,d2
  2794.         move.l  d0,a6
  2795.         lea timerinterrupt-DB(a4),a1
  2796.         moveq   #0,d0       ;Timer A
  2797.         jsr -$6(a6)     ;AddICRVector()
  2798.         tst.l   d0
  2799.         beq.s   got_timer
  2800.         addq.l  #4,d3       ;add base addr index
  2801.         lea timerinterrupt-DB(a4),a1
  2802.         moveq   #1,d0       ;Timer B
  2803.         jsr -$6(a6)     ;AddICRVector()
  2804.         tst.l   d0
  2805.         beq.s   got_timer
  2806. try_CIAB    lea cianame-DB(a4),a1
  2807.         cmp.b   #'a',3(a1)
  2808.         bne.s   initerr
  2809.         addq.b  #1,3(a1)
  2810.         moveq   #8,d3       ;CIAB base addr index = 8
  2811.         bra.w   open_ciares
  2812. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  2813. got_timer   lea craddr+8-DB(a4),a6
  2814.         move.l  cia_addr(pc,d3.w),d0
  2815.         move.l  d0,(a6)
  2816.         sub.w   #$100,d0
  2817.         move.l  d0,-(a6)
  2818.         moveq   #2,d3       ;assume timer B
  2819.         btst    #9,d0       ;timer A or B ?
  2820.         bne.s   got_timerB
  2821.         subq.b  #1,d3       ;not timer B -> subtract 1
  2822.         add.w   #$100,d0    ;calc offset to timer control reg
  2823. got_timerB  add.w   #$900,d0
  2824.         move.l  d0,-(a6)
  2825.         move.l  d0,a0           ;get Control Register
  2826.         and.b   #%10000000,(a0)     ;clear CtrlReg bits 0 - 6
  2827.         move.b  d3,_timeropen-DB(a4)    ;d3: 1 = TimerA 2 = TimerB
  2828.     ENDC
  2829.     IFNE    VBLANK
  2830.         moveq   #5,d0       ;INTB_VERTB
  2831.         lea timerinterrupt-DB(a4),a1
  2832.         jsr -$a8(a6)    ;AddIntServer
  2833.         st  _timeropen-DB(a4)
  2834.     ENDC
  2835.         moveq   #0,d0
  2836. initret:    movem.l (sp)+,a4/a6/d2-d3
  2837.         rts
  2838. initerr:    move.l  d2,d0
  2839.         bra.s   initret
  2840.  
  2841. cia_addr:   dc.l    $BFE501,$BFE701,$BFD500,$BFD700
  2842.  
  2843. _AudioRem:  movem.l a5-a6,-(sp)
  2844.         lea DB,a5
  2845.         moveq   #0,d0
  2846.         move.b  _timeropen,d0
  2847.         beq.s   rem1
  2848. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  2849.         clr.b   _timeropen
  2850.     IFNE    CIAB
  2851.         move.l  _ciaresource,a6
  2852.         lea timerinterrupt-DB(a5),a1
  2853.         subq.b  #1,d0
  2854.         jsr -$c(a6)     ;RemICRVector
  2855.     ENDC
  2856.     IFNE    VBLANK
  2857.         movea.l 4.w,a6
  2858.         lea timerinterrupt(pc),a1
  2859.         moveq   #5,d0
  2860.         jsr -$ae(a6)    ;RemIntServer
  2861.     ENDC
  2862. rem1:
  2863.     IFNE    AUDDEV
  2864.         movea.l 4.w,a6
  2865.         tst.b   audiodevopen-DB(a5)
  2866.         beq.s   rem2
  2867.         move.w  #$000f,$dff096  ;stop audio DMA
  2868. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  2869.         lea allocreq-DB(a5),a1
  2870.         jsr -$1c2(a6)   ;CloseDevice()
  2871.         clr.b   audiodevopen-DB(a5)
  2872. rem2:       moveq   #0,d0
  2873.         move.b  sigbitnum-DB(a5),d0
  2874.         bmi.s   rem3
  2875. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  2876.         jsr -$150(a6)   ;FreeSignal()
  2877.         st  sigbitnum-DB(a5)
  2878. rem3:
  2879.     ENDC
  2880.         movem.l (sp)+,a5-a6
  2881.         rts
  2882.  
  2883.     IFNE    MIDI
  2884. _GetSerial: movem.l a5-a6,-(sp) ;Get serial port for MIDI
  2885.         lea DB,a5
  2886.         bsr.s   GetSer2
  2887.         tst.l   d0      ;got the port??
  2888.         beq.s   rgser       ;yes
  2889.         movea.l 4.w,a6      ;no..try to flush serial.device:
  2890.         jsr -$84(a6)        ;Forbid
  2891.         lea $15e(a6),a0     ;ExecBase->DeviceList
  2892.         lea serdev-DB(a5),a1    ;"serial.device"
  2893.         jsr -$114(a6)       ;FindName
  2894.         tst.l   d0
  2895.         beq.s   serdnotf        ;no serial.device!!
  2896.         move.l  d0,a1
  2897.         jsr -$1b6(a6)       ;RemDevice
  2898. serdnotf:   jsr -$8a(a6)        ;and Permit
  2899.         bsr.s   GetSer2     ;now try it again...
  2900. rgser:      movem.l (sp)+,a5-a6
  2901.         rts
  2902.  
  2903. GetSer2:    movea.l 4.w,a6
  2904.         moveq   #0,d0
  2905.         lea miscresname-DB(a5),a1
  2906.         jsr -$1f2(a6)   ;OpenResource()
  2907.         move.l  d0,miscresbase-DB(a5)
  2908.         tst.l   d0
  2909.         beq.s   gserror
  2910.         move.l  d0,a6
  2911.         lea medname-DB(a5),a1
  2912.         moveq   #0,d0       ;serial port
  2913.         jsr -$6(a6)     ;AllocMiscResource()
  2914.         tst.l   d0
  2915.         bne.s   gserror
  2916.         lea medname-DB(a5),a1
  2917.         moveq   #1,d0       ;serial bits
  2918.         jsr -$6(a6)
  2919.         tst.l   d0
  2920.         beq.s   gs2_allocok
  2921.         moveq   #0,d0
  2922.         jsr -$c(a6)     ;bits failed -> Free serial port
  2923.         bra.s   gserror
  2924. gs2_allocok move.w  $dff01c,d0
  2925.         btst    #0,d0
  2926.         sne intrson-DB(a5)
  2927.         moveq   #0,d0       ;TBE
  2928.         lea serinterrupt-DB(a5),a1
  2929.         move.l  4.w,a6
  2930.         jsr -$a2(a6)    ;SetIntVector()
  2931.         move.l  d0,prevtbe-DB(a5)
  2932.         move.w  #$8001,$dff09a  ;TBE on
  2933.         move.w  #114,$dff032    ;set baud rate (SERPER)
  2934.         st  serportalloc-DB(a5)
  2935.         moveq   #0,d0
  2936.         rts
  2937. gserror:    moveq   #-1,d0
  2938.         rts
  2939.  
  2940. _FreeSerial:    movem.l a5-a6,-(sp)
  2941.         lea DB,a5
  2942.         tst.l   miscresbase-DB(a5)
  2943.         beq.s   retfs
  2944.         tst.b   serportalloc-DB(a5)
  2945.         beq.s   retfs
  2946. wmb_loop    move.w  $dff018,d0  ;WAIT until all data sent
  2947.         btst    #12,d0      ;test TSRE bit of SERDAT
  2948.         beq.s   wmb_loop
  2949.         move.w  #$0001,$dff09a  ;disable TBE
  2950.         movea.l 4.w,a6
  2951.         move.l  prevtbe-DB(a5),a1
  2952.         moveq   #0,d0
  2953.         jsr -$a2(a6)    ;SetIntVector()
  2954. fs_noptbe   movea.l miscresbase-DB(a5),a6
  2955.         moveq   #0,d0       ;serial port
  2956.         jsr -$c(a6)     ;FreeMiscResource()
  2957.         moveq   #1,d0       ;serial bits
  2958.         jsr -$c(a6)
  2959.         clr.b   serportalloc-DB(a5)
  2960.         clr.b   lastcmdbyte-DB(a5)
  2961. retfs:      movem.l (sp)+,a5-a6
  2962.         rts
  2963.  
  2964. ; Message number in d0.
  2965. _InitMIDIDump:  tst.b   serportalloc
  2966.         beq.s   idd_rts
  2967.         movem.l a1/a5/a6,-(sp)  ;a1 = data pointer, d1 = length
  2968.         lea DB,a5
  2969.         movea.l 4.w,a6          ;ExecBase
  2970.         jsr -$78(a6)        ;Disable()
  2971.         cmp.w   #16,dqentries-DB(a5)    ;dump queue full?
  2972.         bge.s   idd_exit        ;exit without doing anything
  2973.         lea dqwriteptr-DB(a5),a1
  2974.         movea.l (a1),a0
  2975.         move.w  d0,(a0)+        ;store message number
  2976.         cmpa.l  a1,a0           ;queue end?
  2977.         bne.s   idd_noresetbuff
  2978.         lea dumpqueue-DB(a5),a0 ;reset write pointer
  2979. idd_noresetbuff move.l  a0,(a1)         ;and write it back.
  2980.         addq.w  #1,dqentries-DB(a5)
  2981.         tst.b   sysx-DB(a5)     ;already sending data?
  2982.         bne.s   idd_exit        ;yes. Don't initiate new send.
  2983.         clr.b   lastcmdbyte-DB(a5)
  2984.         bsr StartNewDump
  2985.         move.w  $dff018,d0      ;SERDATR
  2986.         btst    #13,d0
  2987.         beq.s   idd_exit
  2988.         move.w  #$8001,$dff09c      ;request TBE
  2989. idd_exit    jsr -$7e(a6)        ;Enable()
  2990.         movem.l (sp)+,a1/a5/a6
  2991. idd_rts     rts
  2992.  
  2993. SerIntHandler:  move.w  #$4000,$9a(a0)  ;disable..(Interrupts are enabled anyway)
  2994.         move.w  #1,$9c(a0)          ;clear intreq bit
  2995.         tst.b   sysx-buffptr(a1)        ;sysx??
  2996.         bne.s   sih_sysx
  2997.         move.w  bytesinbuff-buffptr(a1),d0  ;bytesinbuff
  2998.         beq.s   exsih               ;buffer empty
  2999.         movea.l readbuffptr-buffptr(a1),a5  ;get buffer read pointer
  3000.         move.w  #$100,d1            ;Stop bit
  3001.         move.b  (a5)+,d1            ;get byte
  3002.         move.w  d1,$30(a0)          ;and push it to SERDAT
  3003.         cmpa.l  a1,a5               ;shall we reset ptr?
  3004.         bne.s   norrbuffptr         ;not yet..
  3005.         lea -256(a1),a5
  3006. norrbuffptr subq.w  #1,d0               ;one less bytes in buffer
  3007.         move.w  d0,bytesinbuff-buffptr(a1)  ;remember it
  3008.         move.l  a5,readbuffptr-buffptr(a1)  ;push new read ptr back
  3009. exsih       move.w  #$c000,$9a(a0)
  3010.         rts
  3011. sih_sysx    move.w  #$100,d1
  3012.         movea.l sysxptr-buffptr(a1),a5  ;data pointer
  3013.         move.b  (a5)+,d1
  3014.         move.l  a5,sysxptr-buffptr(a1)
  3015.         move.w  d1,$30(a0)      ;-> SERDAT
  3016.         subq.l  #1,sysxleft-buffptr(a1) ;sub data left length
  3017.         bne.s   exsih       ;not 0w
  3018.         lea DB,a5
  3019.         clr.b   lastcmdbyte-DB(a5)
  3020.         bsr.s   StartNewDump
  3021.         bra.s   exsih
  3022.  
  3023. StartNewDump:   tst.w   dqentries-DB(a5)    ;queue empty?
  3024.         beq.s   snd_exit2
  3025.         movea.l dqreadptr-DB(a5),a1 ;get read pointer
  3026.         move.w  (a1)+,d0        ;get message number (D0)
  3027.         cmpa.l  #dqwriteptr,a1      ;queue end?
  3028.         bne.s   snd_noresetbuff
  3029.         lea dumpqueue-DB(a5),a1 ;reset write pointer
  3030. snd_noresetbuff move.l  a1,dqreadptr-DB(a5) ;and write it back.
  3031.         subq.w  #1,dqentries-DB(a5)
  3032. ; then attempt to search the given message (# in D0)
  3033.         move.l  _module-DB(a5),d1
  3034.         beq.s   StartNewDump
  3035.         move.l  d1,a1
  3036.         move.l  mmd_expdata(a1),d1
  3037.         beq.s   StartNewDump
  3038.         move.l  d1,a1
  3039.         move.l  52(a1),d1       ;exp_dump
  3040.         beq.s   StartNewDump
  3041.         move.l  d1,a1
  3042.         cmp.w   (a1),d0
  3043.         bge.s   StartNewDump
  3044.         addq.l  #8,a1           ;points to MMDDump ptr table
  3045.         add.w   d0,d0
  3046.         add.w   d0,d0           ;number *= 4
  3047.         adda.w  d0,a1
  3048.         movea.l (a1),a1
  3049. ; initialize send variables (msg addr. in A0)
  3050. snd_found   move.l  (a1)+,sysxleft-DB(a5)   ;length
  3051.         move.l  (a1),sysxptr-DB(a5) ;data pointer
  3052.         st  sysx-DB(a5)
  3053.         rts
  3054. snd_exit2   clr.b   sysx-DB(a5)     ;finish dump
  3055.         rts
  3056.  
  3057. _AddMIDIData    move.l  a6,-(sp)
  3058.         lea DB,a6
  3059.         bsr.s   _AddMIDId
  3060.         move.l  (sp)+,a6
  3061.         rts
  3062.  
  3063. _AddMIDId   movem.l a1-a3/a5,-(sp)
  3064.         tst.b   serportalloc-DB(a6)
  3065.         beq.s   retamd1
  3066.         movea.l 4.w,a5
  3067.         lea $dff09a,a3
  3068.         move.w  #$4000,(a3) ;Disable interrupts
  3069.         addq.b  #1,$126(a5) ;ExecBase->IDNestCnt
  3070.         lea buffptr-DB(a6),a2   ;end of buffer (ptr)
  3071.         move.w  -130(a3),d1 ;-130(a3) = $dff018 (SERDATR)
  3072.         btst    #13,d1
  3073.         beq.s   noTBEreq
  3074.         move.w  #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  3075. noTBEreq    movea.l (a2),a1     ;buffer pointer
  3076.         subq.w  #1,d0       ;-1 for DBF
  3077. adddataloop move.b  (a0)+,d1    ;get byte
  3078.         bpl.s   norscheck   ;this isn't a status byte
  3079.         cmp.b   #$ef,d1     ;ignore system messages
  3080.         bhi.s   norscheck
  3081.         cmp.b   lastcmdbyte-DB(a6),d1   ;same as previous status byte?
  3082.         beq.s   samesb          ;yes, skip
  3083.         move.b  d1,lastcmdbyte-DB(a6)   ;no, don't skip but store.
  3084. norscheck   move.b  d1,(a1)+        ;push to midi send buffer
  3085.         addq.w  #1,8(a2)
  3086. samesb      cmpa.l  a2,a1           ;end of buffer??
  3087.         bne.s   noresbuffptr        ;no.
  3088.         lea sendbuffer-DB(a6),a1    ;reset
  3089. noresbuffptr    dbf d0,adddataloop
  3090.         move.l  a1,(a2)         ;push back new buffer ptr
  3091.         subq.b  #1,$126(a5)
  3092.         bge.s   retamd1
  3093.         move.w  #$c000,(a3) ;enable interrupts again
  3094. retamd1     movem.l (sp)+,a1-a3/a5
  3095.         rts
  3096.     ENDC
  3097.  
  3098.         DATA
  3099. DB:     ;Data base pointer
  3100.     IFNE    MIDI
  3101. sendbuffer  ds.b    256
  3102. buffptr     dc.l    sendbuffer
  3103. readbuffptr dc.l    sendbuffer
  3104. bytesinbuff dc.w    0
  3105. sysx        dc.b    0
  3106. lastcmdbyte dc.b    0
  3107. sysxptr     dc.l    0
  3108. sysxleft    dc.l    0
  3109. dumpqueue   ds.w    16
  3110. dqwriteptr  dc.l    dumpqueue
  3111. dqreadptr   dc.l    dumpqueue
  3112. dqentries   dc.w    0
  3113.     ENDC
  3114. miscresbase dc.l    0
  3115. timerdiv    dc.l    470000
  3116.     IFNE    AUDDEV
  3117. audiodevopen    dc.b    0
  3118. sigbitnum   dc.b    -1
  3119.     ENDC
  3120.     IFNE    MIDI
  3121. serportalloc    dc.b    0
  3122.     ENDC
  3123.         even
  3124.     IFNE    MIDI
  3125. preschgdata dc.l    0
  3126. noteondata  dc.l    0
  3127.     ENDC
  3128. _module     dc.l    0
  3129. dmaonmsk    dc.w    0 ;\_May not be
  3130.     IFNE    MIDI
  3131. bytesinnotebuff dc.w    0 ;/ separated!
  3132. noteonbuff  ds.b    (MAX_NUMTRACKS+2)*3
  3133.         even
  3134. intrson     dc.b    0,0
  3135. prevtbe     dc.l    0
  3136.     ENDC
  3137.     IFNE    CIAB
  3138. _ciaresource    dc.l    0
  3139. craddr      dc.l    0
  3140.         dc.l    0   ;tloaddr
  3141.         dc.l    0   ;thiaddr
  3142.     ENDC
  3143. timerinterrupt  dc.w    0,0,0,0,0
  3144.         dc.l    timerintname,DB
  3145.         dc.l    _IntHandler
  3146.     IFNE    MIDI
  3147. serinterrupt    dc.w    0,0,0,0,0
  3148.         dc.l    serintname,buffptr,SerIntHandler
  3149.     ENDC
  3150.     IFNE    AUDDEV
  3151. allocport   dc.l    0,0 ;succ, pred
  3152.         dc.b    4,0 ;NT_MSGPORT
  3153.         dc.l    0   ;name
  3154.         dc.b    0,0 ;flags = PA_SIGNAL
  3155.         dc.l    0   ;task
  3156. reqlist     dc.l    0,0,0   ;list head, tail and tailpred
  3157.         dc.b    5,0
  3158. allocreq    dc.l    0,0
  3159.         dc.b    0,127   ;NT_UNKNOWN, use maximum priority (127)
  3160.         dc.l    0,allocport ;name, replyport
  3161.         dc.w    68      ;length
  3162.         dc.l    0   ;io_Device
  3163.         dc.l    0   ;io_Unit
  3164.         dc.w    0   ;io_Command
  3165.         dc.b    0,0 ;io_Flags, io_Error
  3166.         dc.w    0   ;ioa_AllocKey
  3167.         dc.l    sttempo ;ioa_Data
  3168.         dc.l    1   ;ioa_Length
  3169.         dc.w    0,0,0   ;ioa_Period, Volume, Cycles
  3170.         dc.w    0,0,0,0,0,0,0,0,0,0 ;ioa_WriteMsg
  3171. audiodevname    dc.b    'audio.device',0
  3172.     ENDC
  3173.     IFNE    CIAB
  3174. cianame     dc.b    'ciax.resource',0
  3175. _timeropen  dc.b    0
  3176.     ENDC
  3177. timerintname    dc.b    'OMEDTimerInterrupt',0
  3178.     IFNE    MIDI
  3179. serintname  dc.b    'OMEDSerialInterrupt',0
  3180. miscresname dc.b    'misc.resource',0
  3181. serdev      dc.b    'serial.device',0
  3182. medname     dc.b    'OctaMED Pro modplayer',0
  3183.     ENDC
  3184.         even
  3185.     IFNE    MIDI
  3186. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  3187.  
  3188. midicontrnum    ds.b    16
  3189.  
  3190. prevmidicpres   dc.l    0,0,0,0,0,0,0,0 ; 16 * 2 bytes
  3191.  
  3192. prevmidipbend   dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3193.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3194.     ENDC
  3195. ; TRACK-data structures (see definitions at the end of this file)
  3196. t03d        ds.b    TAAOFFS
  3197.         dc.l    $dff0a0
  3198.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3199.         dc.b    $ff
  3200. t03de       ds.b    T03SZ-(t03de-t03d)
  3201.         ds.b    TAAOFFS
  3202.         dc.l    $dff0b0
  3203.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3204.         dc.b    $ff
  3205.         ds.b    T03SZ-(t03de-t03d)
  3206.         ds.b    TAAOFFS
  3207.         dc.l    $dff0c0
  3208.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3209.         dc.b    $ff
  3210.         ds.b    T03SZ-(t03de-t03d)
  3211.         ds.b    TAAOFFS
  3212.         dc.l    $dff0d0
  3213.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3214.         dc.b    $ff
  3215.         ds.b    T03SZ-(t03de-t03d)
  3216. t463d       ds.b    (MAX_NUMTRACKS-4)*T415SZ
  3217. trackdataptrs   dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  3218. ; Build pointer table. This works on Devpac assembler, other assemblers
  3219. ; may need modifications.
  3220. TRKCOUNT    SET 0
  3221.         REPT    (MAX_NUMTRACKS-4)
  3222.         dc.l    t463d+TRKCOUNT
  3223. TRKCOUNT    SET TRKCOUNT+T415SZ
  3224.         ENDR
  3225.  
  3226. nextblock   dc.b    0 ;\ DON'T SEPARATE
  3227. nxtnoclrln  dc.b    0 :/
  3228. numtracks   dc.w    0 ;\ DON'T SEPARATE
  3229. numlines    dc.w    0 ;/
  3230. numpages    dc.w    0
  3231. nextblockline   dc.w    0
  3232. rptline     dc.w    0 ;\ DON'T SEPARATE
  3233. rptcounter  dc.w    0 ;/
  3234. blkdelay    dc.w    0   ;block delay (PT PatternDelay)
  3235. bpmcounter  dc.w    0
  3236. bpmdiv      dc.l    3546895/2
  3237. fxplineblk  dc.l    0   ;for reading effects
  3238.  
  3239. ; Fields in struct InstrExt (easier to access this way rather than
  3240. ; searching through the module).
  3241. holdvals    ds.b 63
  3242. decays      ds.b 63
  3243. finetunes   ds.b 63
  3244. flags       ds.b 63
  3245. ext_midipsets   ds.w 63
  3246. outputdevs  ds.b 63
  3247. playing_aura    ds.b 1
  3248.         EVEN
  3249.  
  3250. ; Below are the period tables. There's one table for each finetune position.
  3251.     IFNE    SYNTH|IFFMOCT
  3252.     dc.w    3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812
  3253.     dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
  3254.     ENDC
  3255. per0    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  3256.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  3257.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3258.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3259.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3260.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3261.     IFNE    SYNTH|IFFMOCT
  3262.     dc.w    3400,3209,3029,2859,2699,2547,2404,2269,2142,2022,1908,1801
  3263.     dc.w    1700,1605,1515,1430,1349,1274,1202,1135,1071,1011,954,901
  3264.     ENDC
  3265. per1    dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  3266.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  3267.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3268.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3269.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3270.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3271.     IFNE    SYNTH|IFFMOCT
  3272.     dc.w    3376,3187,3008,2839,2680,2529,2387,2253,2127,2007,1895,1788
  3273.     dc.w    1688,1593,1504,1419,1340,1265,1194,1127,1063,1004,947,894
  3274.     ENDC
  3275. per2    dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  3276.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  3277.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3278.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3279.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3280.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3281.     IFNE    SYNTH|IFFMOCT
  3282.     dc.w    3352,3164,2986,2819,2660,2511,2370,2237,2112,1993,1881,1776
  3283.     dc.w    1676,1582,1493,1409,1330,1256,1185,1119,1056,997,941,888
  3284.     ENDC
  3285. per3    dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  3286.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  3287.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3288.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3289.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3290.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3291.     IFNE    SYNTH|IFFMOCT
  3292.     dc.w    3328,3141,2965,2799,2641,2493,2353,2221,2097,1979,1868,1763
  3293.     dc.w    1664,1571,1482,1399,1321,1247,1177,1111,1048,989,934,881
  3294.     ENDC
  3295. per4    dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  3296.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  3297.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3298.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3299.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3300.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3301.     IFNE    SYNTH|IFFMOCT
  3302.     dc.w    3304,3119,2944,2778,2622,2475,2336,2205,2081,1965,1854,1750
  3303.     dc.w    1652,1559,1472,1389,1311,1238,1168,1103,1041,982,927,875
  3304.     ENDC
  3305. per5    dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  3306.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  3307.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3308.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3309.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3310.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3311.     IFNE    SYNTH|IFFMOCT
  3312.     dc.w    3280,3096,2922,2758,2603,2457,2319,2189,2066,1950,1841,1738
  3313.     dc.w    1640,1548,1461,1379,1302,1229,1160,1095,1033,975,920,869
  3314.     ENDC
  3315. per6    dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  3316.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  3317.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3318.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3319.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3320.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3321.     IFNE    SYNTH|IFFMOCT
  3322.     dc.w    3256,3073,2901,2738,2584,2439,2302,2173,2051,1936,1827,1725
  3323.     dc.w    1628,1537,1450,1369,1292,1220,1151,1087,1026,968,914,862
  3324.     ENDC
  3325. per7    dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  3326.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  3327.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3328.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3329.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3330.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3331.     IFNE    SYNTH|IFFMOCT
  3332.     dc.w    3628,3424,3232,3051,2880,2718,2565,2421,2285,2157,2036,1922
  3333.     dc.w    1814,1712,1616,1525,1440,1359,1283,1211,1143,1079,1018,961
  3334.     ENDC
  3335. per_8   dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  3336.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  3337.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3338.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3339.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3340.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3341.     IFNE    SYNTH|IFFMOCT
  3342.     dc.w    3588,3387,3197,3017,2848,2688,2537,2395,2260,2133,2014,1901
  3343.     dc.w    1794,1693,1598,1509,1424,1344,1269,1197,1130,1067,1007,950
  3344.     ENDC
  3345. per_7   dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  3346.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  3347.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3348.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3349.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3350.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3351.     IFNE    SYNTH|IFFMOCT
  3352.     dc.w    3576,3375,3186,3007,2838,2679,2529,2387,2253,2126,2007,1894
  3353.     dc.w    1788,1688,1593,1504,1419,1339,1264,1193,1126,1063,1003,947
  3354.     ENDC
  3355. per_6   dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  3356.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  3357.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3358.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3359.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3360.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3361.     IFNE    SYNTH|IFFMOCT
  3362.     dc.w    3548,3349,3161,2984,2816,2658,2509,2368,2235,2110,1991,1879
  3363.     dc.w    1774,1674,1580,1492,1408,1329,1254,1184,1118,1055,996,940
  3364.     ENDC
  3365. per_5   dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  3366.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  3367.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3368.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3369.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3370.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3371.     IFNE    SYNTH|IFFMOCT
  3372.     dc.w    3524,3326,3140,2963,2797,2640,2492,2352,2220,2095,1978,1867
  3373.     dc.w    1762,1663,1570,1482,1399,1320,1246,1176,1110,1048,989,933
  3374.     ENDC
  3375. per_4   dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  3376.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  3377.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3378.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3379.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3380.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3381.     IFNE    SYNTH|IFFMOCT
  3382.     dc.w    3500,3304,3118,2943,2778,2622,2475,2336,2205,2081,1964,1854
  3383.     dc.w    1750,1652,1559,1472,1389,1311,1237,1168,1102,1041,982,927
  3384.     ENDC
  3385. per_3   dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  3386.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  3387.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3388.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3389.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3390.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3391.     IFNE    SYNTH|IFFMOCT
  3392.     dc.w    3472,3277,3093,2920,2756,2601,2455,2317,2187,2064,1949,1839
  3393.     dc.w    1736,1639,1547,1460,1378,1301,1228,1159,1094,1032,974,920
  3394.     ENDC
  3395. per_2   dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  3396.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  3397.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3398.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3399.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3400.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3401.     IFNE    SYNTH|IFFMOCT
  3402.     dc.w    3448,3254,3072,2899,2737,2583,2438,2301,2172,2050,1935,1827
  3403.     dc.w    1724,1627,1536,1450,1368,1292,1219,1151,1086,1025,968,913
  3404.     ENDC
  3405. per_1   dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  3406.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  3407.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3408.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3409.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3410.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3411.  
  3412. _periodtable
  3413.     dc.l    per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
  3414.     dc.l    per1,per2,per3,per4,per5,per6,per7
  3415.  
  3416.     IFND    __G2
  3417.         section "datachip",data,chip ;for A68k
  3418.     ENDC
  3419.     IFD __G2
  3420.         section "datachip",data_c ;this is for Devpac 2
  3421.     ENDC
  3422.         XDEF    _modnum
  3423.     IFNE    EASY
  3424. easymod     INCBIN  "module"    ;<<<<< MODULE NAME HERE!
  3425.     ENDC
  3426. _chipzero   dc.l    0
  3427. _modnum     dc.w    0   ;number of module to play
  3428.  
  3429. ; macros for entering offsets
  3430. DEFWORD MACRO
  3431. \1  EQU OFFS
  3432. OFFS    SET OFFS+2
  3433.     ENDM
  3434. DEFBYTE MACRO
  3435. \1  EQU OFFS
  3436. OFFS    SET OFFS+1
  3437.     ENDM
  3438. DEFLONG MACRO
  3439. \1  EQU OFFS
  3440. OFFS    SET OFFS+4
  3441.     ENDM
  3442.  
  3443. OFFS    SET 0
  3444. ; the track-data structure definition:
  3445.     DEFBYTE trk_prevnote    ;previous note number (0 = none, 1 = C-1..)
  3446.     DEFBYTE trk_previnstr   ;previous instrument number
  3447.     DEFBYTE trk_prevvol ;previous volume
  3448.     DEFBYTE trk_prevmidich  ;previous MIDI channel
  3449.     DEFBYTE trk_prevmidin   ;previous MIDI note
  3450.     DEFBYTE trk_noteoffcnt  ;note-off counter (hold)
  3451.     DEFBYTE trk_inithold    ;default hold for this instrument
  3452.     DEFBYTE trk_initdecay   ;default decay for....
  3453.     DEFBYTE trk_stransp ;instrument transpose
  3454.     DEFBYTE trk_finetune    ;finetune
  3455.     DEFWORD trk_soffset ;new sample offset | don't sep this and 2 below!
  3456.     DEFBYTE trk_miscflags   ;bit: 7 = cmd 3 exists, 0 = cmd E exists
  3457.     DEFBYTE trk_currnote    ;note on CURRENT line (0 = none, 1 = C-1...)
  3458.     DEFBYTE trk_outputdev   ;output device
  3459.     DEFBYTE trk_fxtype  ;fx type: 0 = norm, 1 = none, -1 = MIDI
  3460.     DEFLONG trk_previnstra  ;address of the previous instrument data
  3461.     DEFWORD trk_trackvol
  3462. ; the following data only on tracks 0 - 3
  3463.     DEFWORD trk_prevper ;previous period
  3464.     DEFLONG trk_audioaddr   ;hardware audio channel base address
  3465.     DEFLONG trk_sampleptr   ;pointer to sample
  3466.     DEFWORD trk_samplelen   ;length (>> 1)
  3467.     DEFWORD trk_porttrgper  ;portamento (cmd 3) target period
  3468.     DEFBYTE trk_vibshift    ;vibrato shift for ASR instruction
  3469.     DEFBYTE trk_vibrspd ;vibrato speed/size (cmd 4 qualifier)
  3470.     DEFWORD trk_vibrsz  ;vibrato size
  3471.     DEFLONG trk_synthptr    ;pointer to synthetic/hybrid instrument
  3472.     DEFWORD trk_arpgoffs    ;SYNTH: current arpeggio offset
  3473.     DEFWORD trk_arpsoffs    ;SYNTH: arpeggio restart offset
  3474.     DEFBYTE trk_volxcnt ;SYNTH: volume execute counter
  3475.     DEFBYTE trk_wfxcnt  ;SYNTH: waveform execute counter
  3476.     DEFWORD trk_volcmd  ;SYNTH: volume command pointer
  3477.     DEFWORD trk_wfcmd   ;SYNTH: waveform command pointer
  3478.     DEFBYTE trk_volwait ;SYNTH: counter for WAI (volume list)
  3479.     DEFBYTE trk_wfwait  ;SYNTH: counter for WAI (waveform list)
  3480.     DEFWORD trk_synthvibspd ;SYNTH: vibrato speed
  3481.     DEFWORD trk_wfchgspd    ;SYNTH: period change
  3482.     DEFWORD trk_perchg  ;SYNTH: curr. period change from trk_prevper
  3483.     DEFLONG trk_envptr  ;SYNTH: envelope waveform pointer
  3484.     DEFWORD trk_synvibdep   ;SYNTH: vibrato depth
  3485.     DEFLONG trk_synvibwf    ;SYNTH: vibrato waveform
  3486.     DEFWORD trk_synviboffs  ;SYNTH: vibrato pointer
  3487.     DEFBYTE trk_initvolxspd ;SYNTH: volume execute speed
  3488.     DEFBYTE trk_initwfxspd  ;SYNTH: waveform execute speed
  3489.     DEFBYTE trk_volchgspd   ;SYNTH: volume change
  3490.     DEFBYTE trk_prevnote2   ;SYNTH: previous note
  3491.     DEFBYTE trk_synvol  ;SYNTH: current volume
  3492.     DEFBYTE trk_synthtype   ;>0 = synth, -1 = hybrid, 0 = no synth
  3493.     DEFLONG trk_periodtbl   ;pointer to period table
  3494.     DEFWORD trk_prevportspd ;portamento (cmd 3) speed
  3495.     DEFBYTE trk_decay   ;decay
  3496.     DEFBYTE trk_fadespd ;decay speed
  3497.     DEFLONG trk_envrestart  ;SYNTH: envelope waveform restart point
  3498.     DEFBYTE trk_envcount    ;SYNTH: envelope counter
  3499.     DEFBYTE trk_split   ;0 = this channel not splitted (OctaMED V2)
  3500.     DEFWORD trk_newper  ;new period (for synth use)
  3501.     DEFBYTE trk_vibroffs    ;vibrato table offset \ DON'T SEPARATE
  3502.     DEFBYTE trk_tremoffs    ;tremolo table offset /
  3503.     DEFWORD trk_tremsz  ;tremolo size
  3504.     DEFBYTE trk_tremspd ;tremolo speed
  3505.     DEFBYTE trk_tempvol ;temporary volume (for tremolo)
  3506.     DEFWORD trk_vibradjust  ;vibrato +/- change from base period \ DON'T SEPARATE
  3507.     DEFWORD trk_arpadjust   ;arpeggio +/- change from base period/
  3508.